API completely implemented
authorMathieu Baudier <mbaudier@argeo.org>
Sat, 19 Sep 2009 10:10:54 +0000 (10:10 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Sat, 19 Sep 2009 10:10:54 +0000 (10:10 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@2976 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

12 files changed:
security/demo/init.ldif
security/doc/services-api.txt
security/modules/org.argeo.security.manager.ldap/META-INF/spring/dao.xml
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityDao.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityService.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/BasicArgeoUser.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultSecurityService.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java [new file with mode: 0644]
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java [new file with mode: 0644]
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/SecurityDaoLdap.java [deleted file]
security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java

index bc1512b34384e8cf150cf374cff7cc9e1016d8c3..9fb8d4b6f26b1e4e85cab18b6f0cb0d59e71e27f 100644 (file)
@@ -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
index 2991d13b920b3d73370336bdb10bbb4eedfcf68f..6e0ce4219d83a6ffa0361471b74067005cdc2ae8 100644 (file)
@@ -3,6 +3,9 @@ Security RIA API
 ******************
 USERS
 ******************
+getCredentials.security
+> return : userDetails <json> of the logged user
+
 getUsersList.security
 > param : getNatures <true|false>
 > return : users[] <json> : containing username and roles, and depending on the value of getNatures, the natures.
@@ -10,18 +13,21 @@ getUsersList.security
 userExists.security
 > param : userName <string>
 
-deleteUser.security
+deleteUser.security (ADMIN only)
 > param : userName <string>
 
 getUserDetails.security
 > param : userName <string>
 > return : userDetails <json> : full details (roles, natures, etc).
 
-createUser.security
+createUser.security (ADMIN only)
 > params : userName <string>, password <string> 
 
-updateUserPassword.security
-> param : userName <string>, password <string>, [oldpassword <string>] (depends on the admin being logged in or not)
+updateUserPassword.security (ADMIN only)
+> param : userName <string>, password <string>
+
+updatePassword.security
+> param : password <string>, oldpassword <string>
 
 
 ******************
@@ -31,17 +37,17 @@ getRolesList.security
 > param : aucun
 > return : roles[] <json>
 
-getUsersForRole.security
+#getUsersForRole.security
 > param : roleName <string>, getNatures <true|false>
 > return : users[] <json> (username and eventually natures)
 
-createRole.security
+createRole.security (ADMIN only)
 > param : roleName  <string>
 
-deleteRole.security
+deleteRole.security (ADMIN only)
 > param : roleName  <string>
 
-updateUserRoleLink.security
+#updateUserRoleLink.security
 > params : <string> roleName,  <string> username, <string> action="set|unset"
 
 
@@ -49,11 +55,11 @@ updateUserRoleLink.security
 LINKS & NATURES
 ************************
 
-createUserNature.security
+#createUserNature.security
 > params : natureObject <json>, userName <string>
 
-deleteUserNature.security
+#deleteUserNature.security
 > params : natureObject <json>, userName <string>
 
-updateUserNature.security
+#updateUserNature.security
 > params : natureObject <json>, userName <string>
\ No newline at end of file
index 1d540a398ddefa69fa17b258a4a8cf785b1f173b..dc1ad373b8298b65e2e1ca175df096ef2d26aea1 100644 (file)
@@ -5,7 +5,7 @@
               http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
 
 
-       <bean id="securityDao" class="org.argeo.security.ldap.SecurityDaoLdap">
+       <bean id="securityDao" class="org.argeo.security.ldap.ArgeoSecurityDaoLdap">
                <constructor-arg ref="contextSource" />
                <property name="userDetailsManager" ref="userDetailsManager" />
                <property name="authoritiesPopulator" ref="authoritiesPopulator" />
index 039e549e3430e699f90fb2395be0904e2f47c097..c317e15c1a10a316400ef68a8320f0bdefc7214c 100644 (file)
@@ -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);
index 7eecfb56a511ccc622ee81519f27b1208667a122..77b699d012640007cdf118255ddfd674f3da94d0 100644 (file)
@@ -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();
 }
index c6b8ce1b8fa4bec6c1c8574007ccbcd4f5f2d31b..e7d81d0ec4c47040ee10426f2e1f8dc141f59848 100644 (file)
@@ -18,6 +18,7 @@ public class BasicArgeoUser implements ArgeoUser, Serializable {
 
        public BasicArgeoUser(ArgeoUser argeoUser) {
                username = argeoUser.getUsername();
+               password = argeoUser.getPassword();
                userNatures = new ArrayList<UserNature>(argeoUser.getUserNatures());
                roles = new ArrayList<String>(argeoUser.getRoles());
        }
index 0b8368c6f8de29354850336aa82131b9d762bd4b..a018826f844939b8ce53e4b74d0250f8ca23fef2 100644 (file)
@@ -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<UserNature> 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) {
index 6be432547a4ab468cbd959f293b1661dc6279d21..b69e02a4097115f08fa68e4fe982d663fac47754 100644 (file)
@@ -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 (file)
index 0000000..016a7ba
--- /dev/null
@@ -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 (file)
index 0000000..ae1fcee
--- /dev/null
@@ -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<ArgeoUser> listUsers() {
+               List<String> usernames = (List<String>) ldapTemplate.listBindings(
+                               new DistinguishedName(userBase), new ContextMapper() {
+                                       public Object mapFromContext(Object ctxArg) {
+                                               DirContextAdapter ctx = (DirContextAdapter) ctxArg;
+                                               return ctx.getStringAttribute(usernameAttribute);
+                                       }
+                               });
+
+               List<ArgeoUser> lst = new ArrayList<ArgeoUser>();
+               for (String username : usernames) {
+                       lst.add(createBasicArgeoUser(getDetails(username)));
+               }
+               return lst;
+       }
+
+       @SuppressWarnings("unchecked")
+       public List<String> listEditableRoles() {
+               return (List<String>) 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 (file)
index 27ee444..0000000
+++ /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<ArgeoUser> listUsers() {
-               List<String> usernames = (List<String>) ldapTemplate.listBindings(
-                               new DistinguishedName(userBase), new ContextMapper() {
-                                       public Object mapFromContext(Object ctxArg) {
-                                               DirContextAdapter ctx = (DirContextAdapter) ctxArg;
-                                               return ctx.getStringAttribute(usernameAttribute);
-                                       }
-                               });
-
-               List<ArgeoUser> lst = new ArrayList<ArgeoUser>();
-               for (String username : usernames) {
-                       UserDetails userDetails = userDetailsManager
-                                       .loadUserByUsername(username);
-                       lst.add((ArgeoUser) userDetails);
-               }
-               return lst;
-       }
-
-       @SuppressWarnings("unchecked")
-       public List<String> listEditableRoles() {
-               return (List<String>) 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;
-       }
-}
index 8b09b94a5d273571184cdf6fae90c88029a19a58..e73522cf4a4b6f072c1bd7d750bdd90082dbff65 100644 (file)
@@ -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) {