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