]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/internal/useradmin/SimpleJcrSecurityModel.java
029719c3a858f2236a79a4db819f4a106389da47
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / useradmin / 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 import javax.jcr.version.VersionManager;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.argeo.ArgeoException;
30 import org.argeo.jcr.ArgeoJcrConstants;
31 import org.argeo.jcr.ArgeoNames;
32 import org.argeo.jcr.ArgeoTypes;
33 import org.argeo.jcr.JcrUtils;
34 import org.argeo.jcr.UserJcrUtils;
35 import org.argeo.security.jcr.JcrSecurityModel;
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
50 public synchronized Node sync(Session session, String username,
51 List<String> roles) {
52 // TODO check user name validity (e.g. should not start by ROLE_)
53
54 try {
55 Node userHome = UserJcrUtils.getUserHome(session, username);
56 if (userHome == null) {
57 String homePath = generateUserPath(homeBasePath, username);
58 userHome = JcrUtils.mkdirs(session, homePath);
59 // userHome = JcrUtils.mkfolders(session, homePath);
60 userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
61 userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username);
62 session.save();
63
64 JcrUtils.clearAccessControList(session, homePath, username);
65 JcrUtils.addPrivilege(session, homePath, username,
66 Privilege.JCR_ALL);
67 } else {
68 // for backward compatibility with pre 1.0 security model
69 if (userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) {
70 userHome.getNode(ArgeoNames.ARGEO_PROFILE).remove();
71 userHome.getSession().save();
72 }
73 }
74
75 // Remote roles
76 if (roles != null) {
77 // writeRemoteRoles(userHome, roles);
78 }
79
80 Node userProfile = UserJcrUtils.getUserProfile(session, username);
81 if (userProfile == null) {
82 String personPath = generateUserPath(
83 ArgeoJcrConstants.PEOPLE_BASE_PATH, username);
84 Node personBase = JcrUtils.mkdirs(session, personPath);
85 userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE);
86 userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE);
87 userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username);
88 userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true);
89 userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED,
90 true);
91 userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED,
92 true);
93 userProfile.setProperty(
94 ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, true);
95 session.save();
96
97 JcrUtils.clearAccessControList(session, userProfile.getPath(),
98 username);
99 JcrUtils.addPrivilege(session, userProfile.getPath(), username,
100 Privilege.JCR_READ);
101
102 VersionManager versionManager = session.getWorkspace()
103 .getVersionManager();
104 if (versionManager.isCheckedOut(userProfile.getPath()))
105 versionManager.checkin(userProfile.getPath());
106
107 }
108
109 // Remote roles
110 if (roles != null) {
111 writeRemoteRoles(userProfile, roles);
112 }
113 return userProfile;
114 } catch (RepositoryException e) {
115 JcrUtils.discardQuietly(session);
116 throw new ArgeoException("Cannot sync node security model for "
117 + username, e);
118 }
119 }
120
121 /** Generate path for a new user home */
122 protected String generateUserPath(String base, String username) {
123 int atIndex = username.indexOf('@');
124 if (atIndex > 0) {
125 String domain = username.substring(0, atIndex);
126 String name = username.substring(atIndex + 1);
127 return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/'
128 + domain + '/' + JcrUtils.firstCharsToPath(name, 2) + '/'
129 + name;
130 } else if (atIndex == 0 || atIndex == (username.length() - 1)) {
131 throw new ArgeoException("Unsupported username " + username);
132 } else {
133 return base + '/' + JcrUtils.firstCharsToPath(username, 2) + '/'
134 + username;
135 }
136 }
137
138 /** Write remote roles used by remote access in the home directory */
139 protected void writeRemoteRoles(Node userHome, List<String> roles)
140 throws RepositoryException {
141 boolean writeRoles = false;
142 if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
143 Value[] remoteRoles = userHome.getProperty(
144 ArgeoNames.ARGEO_REMOTE_ROLES).getValues();
145 if (remoteRoles.length != roles.size())
146 writeRoles = true;
147 else
148 for (int i = 0; i < remoteRoles.length; i++)
149 if (!remoteRoles[i].getString().equals(roles.get(i)))
150 writeRoles = true;
151 } else
152 writeRoles = true;
153
154 if (writeRoles) {
155 userHome.getSession().getWorkspace().getVersionManager()
156 .checkout(userHome.getPath());
157 String[] roleIds = roles.toArray(new String[roles.size()]);
158 userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
159 JcrUtils.updateLastModified(userHome);
160 userHome.getSession().save();
161 userHome.getSession().getWorkspace().getVersionManager()
162 .checkin(userHome.getPath());
163 if (log.isDebugEnabled())
164 log.debug("Wrote remote roles " + roles + " for "
165 + userHome.getProperty(ArgeoNames.ARGEO_USER_ID));
166 }
167
168 }
169
170 public void setHomeBasePath(String homeBasePath) {
171 this.homeBasePath = homeBasePath;
172 }
173
174 }