From: Mathieu Baudier Date: Sat, 19 Sep 2009 10:10:54 +0000 (+0000) Subject: API completely implemented X-Git-Tag: argeo-commons-2.1.30~1778 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=ec59a58bc368dc922a454d52eb70bb91dfd68793 API completely implemented git-svn-id: https://svn.argeo.org/commons/trunk@2976 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/security/demo/init.ldif b/security/demo/init.ldif index bc1512b34..9fb8d4b6f 100644 --- a/security/demo/init.ldif +++ b/security/demo/init.ldif @@ -27,6 +27,19 @@ sn: User uid: demo userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9 +dn: uid=root,ou=users,dc=demo,dc=argeo,dc=org +objectClass: person +objectClass: inetOrgPerson +objectClass: organizationalPerson +objectClass: top +cn: demo User +description: Superuser +givenname: Root +mail: root@localhost +sn: Root +uid: root +userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9 + dn: uid=frodo,ou=users,dc=demo,dc=argeo,dc=org objectClass: person objectClass: inetOrgPerson @@ -58,3 +71,4 @@ objectClass: groupOfUniqueNames objectClass: top cn: admin uniquemember: uid=gandalf,ou=users,dc=demo,dc=argeo,dc=org +uniquemember: uid=root,ou=users,dc=demo,dc=argeo,dc=org diff --git a/security/doc/services-api.txt b/security/doc/services-api.txt index 2991d13b9..6e0ce4219 100644 --- a/security/doc/services-api.txt +++ b/security/doc/services-api.txt @@ -3,6 +3,9 @@ Security RIA API ****************** USERS ****************** +getCredentials.security +> return : userDetails of the logged user + getUsersList.security > param : getNatures > return : users[] : containing username and roles, and depending on the value of getNatures, the natures. @@ -10,18 +13,21 @@ getUsersList.security userExists.security > param : userName -deleteUser.security +deleteUser.security (ADMIN only) > param : userName getUserDetails.security > param : userName > return : userDetails : full details (roles, natures, etc). -createUser.security +createUser.security (ADMIN only) > params : userName , password -updateUserPassword.security -> param : userName , password , [oldpassword ] (depends on the admin being logged in or not) +updateUserPassword.security (ADMIN only) +> param : userName , password + +updatePassword.security +> param : password , oldpassword ****************** @@ -31,17 +37,17 @@ getRolesList.security > param : aucun > return : roles[] -getUsersForRole.security +#getUsersForRole.security > param : roleName , getNatures > return : users[] (username and eventually natures) -createRole.security +createRole.security (ADMIN only) > param : roleName -deleteRole.security +deleteRole.security (ADMIN only) > param : roleName -updateUserRoleLink.security +#updateUserRoleLink.security > params : roleName, username, action="set|unset" @@ -49,11 +55,11 @@ updateUserRoleLink.security LINKS & NATURES ************************ -createUserNature.security +#createUserNature.security > params : natureObject , userName -deleteUserNature.security +#deleteUserNature.security > params : natureObject , userName -updateUserNature.security +#updateUserNature.security > params : natureObject , userName \ No newline at end of file diff --git a/security/modules/org.argeo.security.manager.ldap/META-INF/spring/dao.xml b/security/modules/org.argeo.security.manager.ldap/META-INF/spring/dao.xml index 1d540a398..dc1ad373b 100644 --- a/security/modules/org.argeo.security.manager.ldap/META-INF/spring/dao.xml +++ b/security/modules/org.argeo.security.manager.ldap/META-INF/spring/dao.xml @@ -5,7 +5,7 @@ http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"> - + diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityDao.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityDao.java index 039e549e3..c317e15c1 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityDao.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityDao.java @@ -13,6 +13,8 @@ public interface ArgeoSecurityDao { public void delete(String username); + public void createRole(String role, String superuserName); + public void deleteRole(String role); public void updatePassword(String oldPassword, String newPassword); diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityService.java index 7eecfb56a..77b699d01 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityService.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityService.java @@ -1,8 +1,11 @@ package org.argeo.security; - public interface ArgeoSecurityService { public void newUser(ArgeoUser argeoUser); + + public void updateUserPassword(String username, String password); + public void newRole(String role); + public ArgeoSecurityDao getSecurityDao(); } diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/BasicArgeoUser.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/BasicArgeoUser.java index c6b8ce1b8..e7d81d0ec 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/BasicArgeoUser.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/BasicArgeoUser.java @@ -18,6 +18,7 @@ public class BasicArgeoUser implements ArgeoUser, Serializable { public BasicArgeoUser(ArgeoUser argeoUser) { username = argeoUser.getUsername(); + password = argeoUser.getPassword(); userNatures = new ArrayList(argeoUser.getUserNatures()); roles = new ArrayList(argeoUser.getRoles()); } diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java index 0b8368c6f..a018826f8 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java @@ -31,8 +31,8 @@ public class ArgeoUserDetails extends User implements ArgeoUser { } public ArgeoUserDetails(ArgeoUser argeoUser) { - this(argeoUser.getUsername(), argeoUser.getUserNatures(), argeoUser.getPassword(), - rolesToAuthorities(argeoUser.getRoles())); + this(argeoUser.getUsername(), argeoUser.getUserNatures(), argeoUser + .getPassword(), rolesToAuthorities(argeoUser.getRoles())); } public List getUserNatures() { @@ -61,11 +61,15 @@ public class ArgeoUserDetails extends User implements ArgeoUser { } public static BasicArgeoUser createBasicArgeoUser(UserDetails userDetails) { - BasicArgeoUser argeoUser = new BasicArgeoUser(); - argeoUser.setUsername(userDetails.getUsername()); - addAuthoritiesToRoles(userDetails.getAuthorities(), argeoUser - .getRoles()); - return argeoUser; + if (userDetails instanceof ArgeoUser) { + return new BasicArgeoUser((ArgeoUser) userDetails); + } else { + BasicArgeoUser argeoUser = new BasicArgeoUser(); + argeoUser.setUsername(userDetails.getUsername()); + addAuthoritiesToRoles(userDetails.getAuthorities(), argeoUser + .getRoles()); + return argeoUser; + } } public static ArgeoUser asArgeoUser(Authentication authentication) { diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultSecurityService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultSecurityService.java index 6be432547..b69e02a40 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultSecurityService.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultSecurityService.java @@ -4,6 +4,7 @@ import org.argeo.security.ArgeoSecurity; import org.argeo.security.ArgeoSecurityDao; import org.argeo.security.ArgeoSecurityService; import org.argeo.security.ArgeoUser; +import org.argeo.security.BasicArgeoUser; public class DefaultSecurityService implements ArgeoSecurityService { private ArgeoSecurity argeoSecurity = new DefaultArgeoSecurity(); @@ -14,9 +15,13 @@ public class DefaultSecurityService implements ArgeoSecurityService { } public void newRole(String role) { - ArgeoUser superUser = securityDao.getUser(argeoSecurity.getSuperUsername()); - superUser.getRoles().add(role); - securityDao.update(superUser); + securityDao.createRole(role, argeoSecurity.getSuperUsername()); + } + + public void updateUserPassword(String username, String password) { + BasicArgeoUser user = new BasicArgeoUser(securityDao.getUser(username)); + user.setPassword(password); + securityDao.update(user); } public void newUser(ArgeoUser user) { diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java new file mode 100644 index 000000000..016a7bae6 --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java @@ -0,0 +1,19 @@ +package org.argeo.security.ldap; + +import org.springframework.ldap.core.ContextSource; +import org.springframework.ldap.core.DistinguishedName; +import org.springframework.security.userdetails.ldap.LdapUserDetailsManager; + +public class ArgeoLdapUserDetailsManager extends LdapUserDetailsManager { + + public ArgeoLdapUserDetailsManager(ContextSource contextSource) { + super(contextSource); + } + + @Override + protected DistinguishedName buildGroupDn(String group) { + // TODO Auto-generated method stub + return super.buildGroupDn(group); + } + +} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java new file mode 100644 index 000000000..ae1fceea3 --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java @@ -0,0 +1,171 @@ +package org.argeo.security.ldap; + +import static org.argeo.security.core.ArgeoUserDetails.createBasicArgeoUser; + +import java.util.ArrayList; +import java.util.List; + +import javax.naming.Name; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.argeo.security.ArgeoSecurityDao; +import org.argeo.security.ArgeoUser; +import org.argeo.security.core.ArgeoUserDetails; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.ldap.core.ContextExecutor; +import org.springframework.ldap.core.ContextMapper; +import org.springframework.ldap.core.ContextSource; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DistinguishedName; +import org.springframework.ldap.core.LdapTemplate; +import org.springframework.security.ldap.DefaultLdapUsernameToDnMapper; +import org.springframework.security.ldap.LdapUsernameToDnMapper; +import org.springframework.security.ldap.LdapUtils; +import org.springframework.security.userdetails.UserDetails; +import org.springframework.security.userdetails.UserDetailsManager; + +public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean { + // private final static Log log = LogFactory.getLog(UserDaoLdap.class); + + private UserDetailsManager userDetailsManager; + private ArgeoLdapAuthoritiesPopulator authoritiesPopulator; + private String userBase = "ou=users"; + private String usernameAttribute = "uid"; + + private final LdapTemplate ldapTemplate; + + /* TODO: factorize with user details manager */ + private LdapUsernameToDnMapper usernameMapper = null; + + public void afterPropertiesSet() throws Exception { + if (usernameMapper == null) + usernameMapper = new DefaultLdapUsernameToDnMapper(userBase, + usernameAttribute); + } + + public ArgeoSecurityDaoLdap(ContextSource contextSource) { + ldapTemplate = new LdapTemplate(contextSource); + } + + public void create(ArgeoUser user) { + userDetailsManager.createUser(new ArgeoUserDetails(user)); + } + + public ArgeoUser getUser(String uname) { + return createBasicArgeoUser(getDetails(uname)); + } + + @SuppressWarnings("unchecked") + public List listUsers() { + List usernames = (List) ldapTemplate.listBindings( + new DistinguishedName(userBase), new ContextMapper() { + public Object mapFromContext(Object ctxArg) { + DirContextAdapter ctx = (DirContextAdapter) ctxArg; + return ctx.getStringAttribute(usernameAttribute); + } + }); + + List lst = new ArrayList(); + for (String username : usernames) { + lst.add(createBasicArgeoUser(getDetails(username))); + } + return lst; + } + + @SuppressWarnings("unchecked") + public List listEditableRoles() { + return (List) ldapTemplate.listBindings(authoritiesPopulator + .getGroupSearchBase(), new ContextMapper() { + public Object mapFromContext(Object ctxArg) { + String groupName = ((DirContextAdapter) ctxArg) + .getStringAttribute(authoritiesPopulator + .getGroupRoleAttribute()); + String roleName = authoritiesPopulator + .convertGroupToRole(groupName); + return roleName; + } + }); + } + + public void update(ArgeoUser user) { + userDetailsManager.updateUser(new ArgeoUserDetails(user)); + } + + public void delete(String username) { + userDetailsManager.deleteUser(username); + } + + public void updatePassword(String oldPassword, String newPassword) { + userDetailsManager.changePassword(oldPassword, newPassword); + } + + public Boolean userExists(String username) { + return userDetailsManager.userExists(username); + } + + public void createRole(String role, final String superuserName) { + String group = convertRoleToGroup(role); + DistinguishedName superuserDn = (DistinguishedName) ldapTemplate + .executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + return LdapUtils.getFullDn(usernameMapper + .buildDn(superuserName), ctx); + } + }); + + Name groupDn = buildGroupDn(group); + DirContextAdapter context = new DirContextAdapter(); + context.setAttributeValues("objectClass", new String[] { "top", + "groupOfUniqueNames" }); + context.setAttributeValue("cn", group); + + // Add superuser because cannot create empty group + context.setAttributeValue("uniqueMember", superuserDn.toString()); + + ldapTemplate.bind(groupDn, context, null); + } + + public void deleteRole(String role) { + String group = convertRoleToGroup(role); + Name dn = buildGroupDn(group); + ldapTemplate.unbind(dn); + } + + protected String convertRoleToGroup(String role) { + // FIXME: factorize with spring security + String group = role; + if (group.startsWith("ROLE_")) { + group = group.substring("ROLE_".length()); + group = group.toLowerCase(); + } + return group; + } + + protected Name buildGroupDn(String name) { + return new DistinguishedName("cn=" + name + "," + + authoritiesPopulator.getGroupSearchBase()); + } + + public void setUserDetailsManager(UserDetailsManager userDetailsManager) { + this.userDetailsManager = userDetailsManager; + } + + public void setUserBase(String userBase) { + this.userBase = userBase; + } + + public void setUsernameAttribute(String usernameAttribute) { + this.usernameAttribute = usernameAttribute; + } + + public void setAuthoritiesPopulator( + ArgeoLdapAuthoritiesPopulator authoritiesPopulator) { + this.authoritiesPopulator = authoritiesPopulator; + } + + protected UserDetails getDetails(String username) { + return userDetailsManager.loadUserByUsername(username); + } +} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/SecurityDaoLdap.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/SecurityDaoLdap.java deleted file mode 100644 index 27ee4443c..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/SecurityDaoLdap.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.argeo.security.ldap; - -import java.util.ArrayList; -import java.util.List; - -import javax.naming.Name; - -import org.argeo.security.ArgeoSecurityDao; -import org.argeo.security.ArgeoUser; -import org.argeo.security.core.ArgeoUserDetails; -import org.springframework.ldap.core.ContextMapper; -import org.springframework.ldap.core.ContextSource; -import org.springframework.ldap.core.DirContextAdapter; -import org.springframework.ldap.core.DistinguishedName; -import org.springframework.ldap.core.LdapTemplate; -import org.springframework.security.userdetails.UserDetails; -import org.springframework.security.userdetails.UserDetailsManager; - -public class SecurityDaoLdap implements ArgeoSecurityDao { - // private final static Log log = LogFactory.getLog(UserDaoLdap.class); - - private UserDetailsManager userDetailsManager; - private ArgeoLdapAuthoritiesPopulator authoritiesPopulator; - private String userBase = "ou=users"; - private String usernameAttribute = "uid"; - - private final LdapTemplate ldapTemplate; - - public SecurityDaoLdap(ContextSource contextSource) { - ldapTemplate = new LdapTemplate(contextSource); - } - - public void create(ArgeoUser user) { - userDetailsManager.createUser(new ArgeoUserDetails(user)); - } - - public ArgeoUser getUser(String uname) { - return (ArgeoUser) userDetailsManager.loadUserByUsername(uname); - } - - @SuppressWarnings("unchecked") - public List listUsers() { - List usernames = (List) ldapTemplate.listBindings( - new DistinguishedName(userBase), new ContextMapper() { - public Object mapFromContext(Object ctxArg) { - DirContextAdapter ctx = (DirContextAdapter) ctxArg; - return ctx.getStringAttribute(usernameAttribute); - } - }); - - List lst = new ArrayList(); - for (String username : usernames) { - UserDetails userDetails = userDetailsManager - .loadUserByUsername(username); - lst.add((ArgeoUser) userDetails); - } - return lst; - } - - @SuppressWarnings("unchecked") - public List listEditableRoles() { - return (List) ldapTemplate.listBindings(authoritiesPopulator - .getGroupSearchBase(), new ContextMapper() { - public Object mapFromContext(Object ctxArg) { - String groupName = ((DirContextAdapter) ctxArg) - .getStringAttribute(authoritiesPopulator - .getGroupRoleAttribute()); - String roleName = authoritiesPopulator - .convertGroupToRole(groupName); - return roleName; - } - }); - } - - public void update(ArgeoUser user) { - userDetailsManager.updateUser(new ArgeoUserDetails(user)); - } - - public void delete(String username) { - userDetailsManager.deleteUser(username); - } - - public void updatePassword(String oldPassword, String newPassword) { - userDetailsManager.changePassword(oldPassword, newPassword); - } - - public Boolean userExists(String username) { - return userDetailsManager.userExists(username); - } - - public void deleteRole(String role) { - if(true) - throw new UnsupportedOperationException(); - - Name dn = buildRoleDn(role); - DirContextAdapter context = new DirContextAdapter(); - context.setAttributeValues("objectClass", new String[] { "top", - "groupOfUniqueNames" }); - context.setAttributeValue("cn", role); - ldapTemplate.bind(dn, context, null); - } - - protected Name buildRoleDn(String name) { - return new DistinguishedName("cn=" + name + "," - + authoritiesPopulator.getGroupSearchBase()); - } - - - public void setUserDetailsManager(UserDetailsManager userDetailsManager) { - this.userDetailsManager = userDetailsManager; - } - - public void setUserBase(String userBase) { - this.userBase = userBase; - } - - public void setUsernameAttribute(String usernameAttribute) { - this.usernameAttribute = usernameAttribute; - } - - public void setAuthoritiesPopulator( - ArgeoLdapAuthoritiesPopulator authoritiesPopulator) { - this.authoritiesPopulator = authoritiesPopulator; - } -} diff --git a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java b/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java index 8b09b94a5..e73522cf4 100644 --- a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java +++ b/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java @@ -128,7 +128,25 @@ public class UsersRolesController implements MvcConstants { @ModelAttribute(ANSWER_MODEL_KEY) public ServerAnswer deleteRole(@RequestParam("role") String role) { securityService.getSecurityDao().deleteRole(role); - return ServerAnswer.ok("Role " + role + " created"); + return ServerAnswer.ok("Role " + role + " deleted"); + } + + @RequestMapping("/updateUserPassword.security") + @ModelAttribute(ANSWER_MODEL_KEY) + public ServerAnswer updateUserPassword( + @RequestParam("username") String username, + @RequestParam("password") String password) { + securityService.updateUserPassword(username, password); + return ServerAnswer.ok("Password updated for user " + username); + } + + @RequestMapping("/updatePassword.security") + @ModelAttribute(ANSWER_MODEL_KEY) + public ServerAnswer updatePassword( + @RequestParam("password") String password, + @RequestParam("oldPassword") String oldPassword) { + securityService.getSecurityDao().updatePassword(oldPassword, password); + return ServerAnswer.ok("Password updated"); } protected void cleanUserBeforeCreate(ArgeoUser user) {