]> git.argeo.org Git - lgpl/argeo-commons.git/blob - SimpleJcrSecurityModel.java
9d26f13352ffbccbfb5ed9a6f237f0be2a707b91
[lgpl/argeo-commons.git] / SimpleJcrSecurityModel.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.cms.internal.useradmin;
17
18 import java.util.List;
19
20 import javax.jcr.Node;
21 import javax.jcr.RepositoryException;
22 import javax.jcr.Session;
23 import javax.jcr.Value;
24 import javax.jcr.security.Privilege;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.jackrabbit.core.security.user.UserAccessControlProvider;
29 import org.argeo.ArgeoException;
30 import org.argeo.cms.internal.auth.JcrSecurityModel;
31 import org.argeo.jcr.ArgeoJcrConstants;
32 import org.argeo.jcr.ArgeoNames;
33 import org.argeo.jcr.ArgeoTypes;
34 import org.argeo.jcr.JcrUtils;
35 import org.argeo.jcr.UserJcrUtils;
36
37 /**
38 * Manages data expected by the Argeo security model, such as user home and
39 * profile.
40 */
41 public class SimpleJcrSecurityModel implements JcrSecurityModel {
42 private final static Log log = LogFactory
43 .getLog(SimpleJcrSecurityModel.class);
44 // ArgeoNames not implemented as interface in order to ease derivation by
45 // Jackrabbit bundles
46
47 /** The home base path. */
48 private String homeBasePath = "/home";
49 private String peopleBasePath = ArgeoJcrConstants.PEOPLE_BASE_PATH;
50
51 @Override
52 public void init(Session adminSession) throws RepositoryException {
53 JcrUtils.mkdirs(adminSession, homeBasePath);
54 JcrUtils.mkdirs(adminSession, peopleBasePath);
55 adminSession.save();
56
57 JcrUtils.addPrivilege(adminSession, homeBasePath,
58 UserAccessControlProvider.USER_ADMIN_GROUP_NAME,
59 Privilege.JCR_READ);
60 JcrUtils.addPrivilege(adminSession, peopleBasePath,
61 UserAccessControlProvider.USER_ADMIN_GROUP_NAME,
62 Privilege.JCR_ALL);
63 }
64
65 public synchronized Node sync(Session session, String username,
66 List<String> roles) {
67 // TODO check user name validity (e.g. should not start by ROLE_)
68
69 try {
70 Node userHome = UserJcrUtils.getUserHome(session, username);
71 if (userHome == null) {
72 String homePath = generateUserPath(homeBasePath, username);
73 userHome = JcrUtils.mkdirs(session, homePath);
74 // userHome = JcrUtils.mkfolders(session, homePath);
75 userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
76 userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username);
77 session.save();
78
79 JcrUtils.clearAccessControList(session, homePath, username);
80 JcrUtils.addPrivilege(session, homePath, username,
81 Privilege.JCR_ALL);
82 } else {
83 // for backward compatibility with pre 1.0 security model
84 if (userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) {
85 userHome.getNode(ArgeoNames.ARGEO_PROFILE).remove();
86 userHome.getSession().save();
87 }
88 }
89
90 // Remote roles
91 if (roles != null) {
92 // writeRemoteRoles(userHome, roles);
93 }
94
95 Node userProfile = UserJcrUtils.getUserProfile(session, username);
96 // new user
97 if (userProfile == null) {
98 String personPath = generateUserPath(peopleBasePath, username);
99 Node personBase = JcrUtils.mkdirs(session, personPath);
100 userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE);
101 userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE);
102 userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username);
103 userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true);
104 userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED,
105 true);
106 userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED,
107 true);
108 userProfile.setProperty(
109 ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, true);
110 session.save();
111
112 JcrUtils.clearAccessControList(session, userProfile.getPath(),
113 username);
114 JcrUtils.addPrivilege(session, userProfile.getPath(), username,
115 Privilege.JCR_READ);
116 }
117
118 // Remote roles
119 if (roles != null) {
120 writeRemoteRoles(userProfile, roles);
121 }
122 return userProfile;
123 } catch (RepositoryException e) {
124 JcrUtils.discardQuietly(session);
125 throw new ArgeoException("Cannot sync node security model for "
126 + username, e);
127 }
128 }
129
130 /** Generate path for a new user home */
131 protected String generateUserPath(String base, String username) {
132 int atIndex = username.indexOf('@');
133 if (atIndex > 0) {
134 String domain = username.substring(0, atIndex);
135 String name = username.substring(atIndex + 1);
136 return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/'
137 + domain + '/' + JcrUtils.firstCharsToPath(name, 2) + '/'
138 + name;
139 } else if (atIndex == 0 || atIndex == (username.length() - 1)) {
140 throw new ArgeoException("Unsupported username " + username);
141 } else {
142 return base + '/' + JcrUtils.firstCharsToPath(username, 2) + '/'
143 + username;
144 }
145 }
146
147 /** Write remote roles used by remote access in the home directory */
148 protected void writeRemoteRoles(Node userHome, List<String> roles)
149 throws RepositoryException {
150 boolean writeRoles = false;
151 if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
152 Value[] remoteRoles = userHome.getProperty(
153 ArgeoNames.ARGEO_REMOTE_ROLES).getValues();
154 if (remoteRoles.length != roles.size())
155 writeRoles = true;
156 else
157 for (int i = 0; i < remoteRoles.length; i++)
158 if (!remoteRoles[i].getString().equals(roles.get(i)))
159 writeRoles = true;
160 } else
161 writeRoles = true;
162
163 if (writeRoles) {
164 userHome.getSession().getWorkspace().getVersionManager()
165 .checkout(userHome.getPath());
166 String[] roleIds = roles.toArray(new String[roles.size()]);
167 userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
168 JcrUtils.updateLastModified(userHome);
169 userHome.getSession().save();
170 userHome.getSession().getWorkspace().getVersionManager()
171 .checkin(userHome.getPath());
172 if (log.isDebugEnabled())
173 log.debug("Wrote remote roles " + roles + " for "
174 + userHome.getProperty(ArgeoNames.ARGEO_USER_ID));
175 }
176
177 }
178
179 public void setHomeBasePath(String homeBasePath) {
180 this.homeBasePath = homeBasePath;
181 }
182
183 }