package org.argeo.cms.internal.useradmin.jackrabbit;
+import static org.argeo.cms.KernelHeader.ROLE_ADMIN;
+import static org.argeo.cms.KernelHeader.USERNAME_ADMIN;
+import static org.argeo.cms.KernelHeader.USERNAME_DEMO;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
+import javax.jcr.version.VersionManager;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.core.security.authentication.CryptedSimpleCredentials;
+import org.apache.jackrabbit.core.security.user.UserAccessControlProvider;
import org.argeo.ArgeoException;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.KernelHeader;
+import org.argeo.cms.internal.auth.GrantedAuthorityPrincipal;
+import org.argeo.cms.internal.auth.JcrSecurityModel;
import org.argeo.jcr.JcrUtils;
import org.argeo.jcr.UserJcrUtils;
import org.argeo.security.NodeAuthenticationToken;
+import org.argeo.security.SecurityUtils;
import org.argeo.security.UserAdminService;
-import org.argeo.cms.internal.auth.GrantedAuthorityPrincipal;
-import org.argeo.security.jcr.JcrSecurityModel;
import org.argeo.security.jcr.JcrUserDetails;
+import org.argeo.security.jcr.NewUserDetails;
import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
*/
public class JackrabbitUserAdminService implements UserAdminService,
AuthenticationProvider {
- final static String userRole = "ROLE_USER";
- final static String adminRole = "ROLE_ADMIN";
+ private final static String JACKR_ADMINISTRATORS = "administrators";
+ private final static String REP_PRINCIPAL_NAME = "rep:principalName";
+ // private final static String REP_PASSWORD = "rep:password";
private Repository repository;
private JcrSecurityModel securityModel;
private JackrabbitSession adminSession = null;
- private String superUsername = "root";
- private String superUserInitialPassword = "demo";
+ private String initialPassword = "demo";
public void init() throws RepositoryException {
Authentication authentication = SecurityContextHolder.getContext()
.getAuthentication();
authentication.getName();
adminSession = (JackrabbitSession) repository.login();
- Authorizable adminGroup = getUserManager().getAuthorizable(adminRole);
+ Authorizable adminGroup = getUserManager().getAuthorizable(ROLE_ADMIN);
if (adminGroup == null) {
- adminGroup = getUserManager().createGroup(adminRole);
+ adminGroup = getUserManager().createGroup(ROLE_ADMIN);
adminSession.save();
}
- Authorizable superUser = getUserManager()
- .getAuthorizable(superUsername);
+
+ // create superuser
+ Authorizable superUser = getUserManager().getAuthorizable(
+ USERNAME_ADMIN);
if (superUser == null) {
- superUser = getUserManager().createUser(superUsername,
- superUserInitialPassword);
+ superUser = getUserManager().createUser(USERNAME_ADMIN,
+ initialPassword);
((Group) adminGroup).addMember(superUser);
- securityModel.sync(adminSession, superUsername, null);
+ securityModel.sync(adminSession, USERNAME_ADMIN, null);
+ adminSession.save();
+
+ // create demo user only at initialisation
+ Authorizable demoUser = getUserManager().getAuthorizable(
+ USERNAME_DEMO);
+ if (demoUser != null)
+ throw new CmsException("There is already a demo user");
+ demoUser = getUserManager().createUser(USERNAME_DEMO,
+ initialPassword);
+ securityModel.sync(adminSession, USERNAME_DEMO, null);
adminSession.save();
}
+ securityModel.init(adminSession);
}
public void destroy() throws RepositoryException {
@Override
public void createUser(UserDetails user) {
try {
- // FIXME workaround for issue in new user wizard where
- // security model is hardcoded and it already exists
- if (getUserManager().getAuthorizable(user.getUsername()) == null) {
- getUserManager().createUser(user.getUsername(),
- user.getPassword());
- securityModel.sync(adminSession, user.getUsername(), null);
- }
+ // if (getUserManager().getAuthorizable(user.getUsername()) == null)
+ // {
+ getUserManager().createUser(user.getUsername(), user.getPassword());
+ Node userProfile = securityModel.sync(adminSession,
+ user.getUsername(), null);
+ if (user instanceof NewUserDetails)
+ ((NewUserDetails) user).mapToProfileNode(userProfile);
+ userProfile.getSession().save();
+
+ // check in node
+ VersionManager versionManager = userProfile.getSession()
+ .getWorkspace().getVersionManager();
+ if (versionManager.isCheckedOut(userProfile.getPath()))
+ versionManager.checkin(userProfile.getPath());
+ // }
updateUser(user);
} catch (RepositoryException e) {
throw new ArgeoException("Cannot create user " + user, e);
@Override
public void updateUser(UserDetails userDetails) {
try {
- User user = (User) getUserManager().getAuthorizable(
- userDetails.getUsername());
+ String username = userDetails.getUsername();
+ User user = (User) getUserManager().getAuthorizable(username);
if (user == null)
throw new ArgeoException("No user " + userDetails.getUsername());
// new password
String newPassword = userDetails.getPassword();
if (!newPassword.trim().equals("")) {
- SimpleCredentials sp = new SimpleCredentials(
- userDetails.getUsername(), newPassword.toCharArray());
- CryptedSimpleCredentials credentials = (CryptedSimpleCredentials) user
- .getCredentials();
- if (!credentials.matches(sp))
- user.changePassword(new String(newPassword));
+ if (newPassword.startsWith("{SHA-256}")) {
+ // Already hashed password
+ throw new CmsException("Cannot import hashed password");
+ // Value v = adminSession.getValueFactory().createValue(
+ // newPassword);
+ // user.setProperty(REP_PASSWORD, v);
+ // TODO find a way to deal w/ protected property
+ // see
+ // http://jackrabbit.apache.org/api/2.2/org/apache/jackrabbit/core/security/user/UserImporter.html
+ } else {
+ SimpleCredentials sp = new SimpleCredentials(
+ userDetails.getUsername(),
+ newPassword.toCharArray());
+ CryptedSimpleCredentials credentials = (CryptedSimpleCredentials) user
+ .getCredentials();
+
+ if (!credentials.matches(sp))
+ user.changePassword(new String(newPassword));
+ }
}
List<String> roles = new ArrayList<String>();
for (GrantedAuthority ga : userDetails.getAuthorities()) {
- if (ga.getAuthority().equals(userRole))
+ if (ga.getAuthority().equals(KernelHeader.ROLE_USER))
continue;
roles.add(ga.getAuthority());
}
- for (Iterator<Group> it = user.memberOf(); it.hasNext();) {
+ groups: for (Iterator<Group> it = user.memberOf(); it.hasNext();) {
Group group = it.next();
- if (roles.contains(group.getPrincipal().getName()))
- roles.remove(group.getPrincipal().getName());
- else
+ String groupName = group.getPrincipal().getName();
+ String role = groupNameToRole(groupName);
+ if (role == null)
+ continue groups;
+
+ if (roles.contains(role))
+ roles.remove(role);
+ else {
group.removeMember(user);
+ if (role.equals(KernelHeader.ROLE_ADMIN)) {
+ Group administratorsGroup = ((Group) getUserManager()
+ .getAuthorizable(JACKR_ADMINISTRATORS));
+ if (administratorsGroup.isDeclaredMember(user))
+ administratorsGroup.removeMember(user);
+ }
+ }
}
- // remaining (new ones)
+ // remaining (new memberships)
for (String role : roles) {
- Group group = (Group) getUserManager().getAuthorizable(role);
+ String groupName = roleToGroupName(role);
+ Group group = (Group) getUserManager().getAuthorizable(
+ groupName);
if (group == null)
throw new ArgeoException("Group " + role
+ " does not exist,"
+ " whereas it was granted to user " + userDetails);
group.addMember(user);
+
+ // add to Jackrabbit administrators
+ if (role.equals(KernelHeader.ROLE_ADMIN)) {
+ Group administratorsGroup = (Group) getUserManager()
+ .getAuthorizable(JACKR_ADMINISTRATORS);
+ administratorsGroup.addMember(user);
+ }
+
}
} catch (Exception e) {
throw new ArgeoException("Cannot update user details", e);
LinkedHashSet<String> res = new LinkedHashSet<String>();
try {
Iterator<Authorizable> groups = getUserManager().findAuthorizables(
- "rep:principalName", null, UserManager.SEARCH_TYPE_GROUP);
+ REP_PRINCIPAL_NAME, null, UserManager.SEARCH_TYPE_GROUP);
while (groups.hasNext()) {
- res.add(groups.next().getPrincipal().getName());
+ Group group = (Group) groups.next();
+ String groupName = group.getPrincipal().getName();
+ String role = groupNameToRole(groupName);
+ if (role != null
+ && !role.equals(KernelHeader.ROLE_GROUP_ADMIN)
+ && !(role.equals(KernelHeader.ROLE_ADMIN) && !SecurityUtils
+ .hasCurrentThreadAuthority(KernelHeader.ROLE_ADMIN)))
+ res.add(role);
}
return res;
} catch (RepositoryException e) {
}
}
+ protected String roleToGroupName(String role) {
+ String groupName;
+ if (role.equals(KernelHeader.ROLE_USER_ADMIN))
+ groupName = UserAccessControlProvider.USER_ADMIN_GROUP_NAME;
+ else if (role.equals(KernelHeader.ROLE_GROUP_ADMIN))
+ groupName = UserAccessControlProvider.GROUP_ADMIN_GROUP_NAME;
+ else
+ groupName = role;
+ return groupName;
+ }
+
+ protected String groupNameToRole(String groupName) {
+ String role;
+ if (groupName.equals(UserAccessControlProvider.USER_ADMIN_GROUP_NAME)) {
+ role = KernelHeader.ROLE_USER_ADMIN;
+ } else if (groupName
+ .equals(UserAccessControlProvider.GROUP_ADMIN_GROUP_NAME)) {
+ role = KernelHeader.ROLE_GROUP_ADMIN;
+ } else if (groupName.equals(JACKR_ADMINISTRATORS)) {
+ return null;
+ } else {
+ role = groupName;
+ }
+ return role;
+ }
+
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
if (username == null)
username = session.getUserID();
User user = (User) getUserManager().getAuthorizable(username);
+
ArrayList<GrantedAuthorityPrincipal> authorities = new ArrayList<GrantedAuthorityPrincipal>();
- // FIXME make it more generic
- authorities.add(new GrantedAuthorityPrincipal("ROLE_USER"));
- Iterator<Group> groups = user.declaredMemberOf();
+ authorities.add(new GrantedAuthorityPrincipal(KernelHeader.ROLE_USER));
+
+ Group adminGroup = (Group) getUserManager().getAuthorizable(
+ KernelHeader.ROLE_ADMIN);
+
+ Iterator<? extends Authorizable> groups;
+ if (username.equals(KernelHeader.USERNAME_ADMIN)
+ || adminGroup.isDeclaredMember(user)) {
+ groups = getUserManager().findAuthorizables(REP_PRINCIPAL_NAME,
+ null, UserManager.SEARCH_TYPE_GROUP);
+ } else {
+ groups = user.declaredMemberOf();
+ }
+
while (groups.hasNext()) {
- Group group = groups.next();
- // String role = "ROLE_"
- // + group.getPrincipal().getName().toUpperCase();
- String role = group.getPrincipal().getName();
- authorities.add(new GrantedAuthorityPrincipal(role));
+ Authorizable group = groups.next();
+ String groupName = group.getPrincipal().getName();
+ String role = groupNameToRole(groupName);
+ if (role != null)
+ authorities.add(new GrantedAuthorityPrincipal(role));
}
Node userProfile = UserJcrUtils.getUserProfile(session, username);