]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SimpleJcrSecurityModel.java
Moves Spring Security / Jackrabbit synchronization in JcrSecurityModel
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.core / src / main / java / org / argeo / security / jcr / SimpleJcrSecurityModel.java
1 package org.argeo.security.jcr;
2
3 import java.util.List;
4
5 import javax.jcr.Node;
6 import javax.jcr.RepositoryException;
7 import javax.jcr.Session;
8 import javax.jcr.Value;
9 import javax.jcr.security.Privilege;
10 import javax.jcr.version.VersionManager;
11
12 import org.apache.commons.logging.Log;
13 import org.apache.commons.logging.LogFactory;
14 import org.argeo.ArgeoException;
15 import org.argeo.jcr.ArgeoJcrConstants;
16 import org.argeo.jcr.ArgeoNames;
17 import org.argeo.jcr.ArgeoTypes;
18 import org.argeo.jcr.JcrUtils;
19 import org.argeo.jcr.UserJcrUtils;
20
21 /**
22 * Manages data expected by the Argeo security model, such as user home and
23 * profile.
24 */
25 public class SimpleJcrSecurityModel implements JcrSecurityModel {
26 private final static Log log = LogFactory
27 .getLog(SimpleJcrSecurityModel.class);
28 // ArgeoNames not implemented as interface in order to ease derivation by
29 // Jackrabbit bundles
30
31 /** The home base path. */
32 private String homeBasePath = "/home";
33
34 public Node sync(Session session, String username, List<String> roles) {
35 // TODO check user name validity (e.g. should not start by ROLE_)
36
37 try {
38 Node userHome = UserJcrUtils.getUserHome(session, username);
39 if (userHome == null) {
40 String homePath = generateUserPath(homeBasePath, username);
41 userHome = JcrUtils.mkdirs(session, homePath);
42 // userHome = JcrUtils.mkfolders(session, homePath);
43 userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
44 userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username);
45 session.save();
46
47 JcrUtils.clearAccessControList(session, homePath, username);
48 JcrUtils.addPrivilege(session, homePath, username,
49 Privilege.JCR_ALL);
50 } else {
51 // for backward compatibility with pre 1.0 security model
52 if (userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) {
53 userHome.getNode(ArgeoNames.ARGEO_PROFILE).remove();
54 userHome.getSession().save();
55 }
56 }
57
58 // Remote roles
59 if (roles != null) {
60 //writeRemoteRoles(userHome, roles);
61 }
62
63 Node userProfile = UserJcrUtils.getUserProfile(session, username);
64 if (userProfile == null) {
65 String personPath = generateUserPath(
66 ArgeoJcrConstants.PEOPLE_BASE_PATH, username);
67 Node personBase = JcrUtils.mkdirs(session, personPath);
68 userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE);
69 userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE);
70 userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username);
71 userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true);
72 userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED,
73 true);
74 userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED,
75 true);
76 userProfile.setProperty(
77 ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, true);
78 session.save();
79
80 JcrUtils.clearAccessControList(session, userProfile.getPath(),
81 username);
82 JcrUtils.addPrivilege(session, userProfile.getPath(), username,
83 Privilege.JCR_READ);
84
85 VersionManager versionManager = session.getWorkspace()
86 .getVersionManager();
87 if (versionManager.isCheckedOut(userProfile.getPath()))
88 versionManager.checkin(userProfile.getPath());
89 }
90 return userProfile;
91 } catch (RepositoryException e) {
92 JcrUtils.discardQuietly(session);
93 throw new ArgeoException("Cannot sync node security model for "
94 + username, e);
95 }
96 }
97
98 /** Generate path for a new user home */
99 protected String generateUserPath(String base, String username) {
100 int atIndex = username.indexOf('@');
101 if (atIndex > 0) {
102 String domain = username.substring(0, atIndex);
103 String name = username.substring(atIndex + 1);
104 return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/'
105 + domain + '/' + JcrUtils.firstCharsToPath(name, 2) + '/'
106 + name;
107 } else if (atIndex == 0 || atIndex == (username.length() - 1)) {
108 throw new ArgeoException("Unsupported username " + username);
109 } else {
110 return base + '/' + JcrUtils.firstCharsToPath(username, 2) + '/'
111 + username;
112 }
113 }
114
115 /** Write remote roles used by remote access in the home directory */
116 protected void writeRemoteRoles(Node userHome, List<String> roles)
117 throws RepositoryException {
118 boolean writeRoles = false;
119 if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
120 Value[] remoteRoles = userHome.getProperty(
121 ArgeoNames.ARGEO_REMOTE_ROLES).getValues();
122 if (remoteRoles.length != roles.size())
123 writeRoles = true;
124 else
125 for (int i = 0; i < remoteRoles.length; i++)
126 if (!remoteRoles[i].getString().equals(roles.get(i)))
127 writeRoles = true;
128 } else
129 writeRoles = true;
130
131 if (writeRoles) {
132 userHome.getSession().getWorkspace().getVersionManager()
133 .checkout(userHome.getPath());
134 String[] roleIds = roles.toArray(new String[roles.size()]);
135 userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
136 JcrUtils.updateLastModified(userHome);
137 userHome.getSession().save();
138 userHome.getSession().getWorkspace().getVersionManager()
139 .checkin(userHome.getPath());
140 if (log.isDebugEnabled())
141 log.debug("Wrote remote roles " + roles + " for "
142 + userHome.getProperty(ArgeoNames.ARGEO_USER_ID));
143 }
144
145 }
146
147 public void setHomeBasePath(String homeBasePath) {
148 this.homeBasePath = homeBasePath;
149 }
150
151 }