#log4j.logger.org.springframework.jms=WARN
log4j.logger.org.springframework.security=DEBUG
+log4j.org.apache.directory=ERROR
+
log4j.logger.org.apache.catalina=INFO
log4j.logger.org.apache.coyote=INFO
log4j.logger.org.apache.tomcat=INFO
<bean id="userDao" class="org.argeo.security.ldap.UserDaoLdap">
<constructor-arg ref="contextSource" />
<property name="userDetailsManager" ref="userDetailsManager" />
+ </bean>
+
+ <bean id="roleDao" class="org.argeo.security.ldap.RoleDaoLdap">
+ <constructor-arg ref="contextSource" />
<property name="authoritiesPopulator" ref="authoritiesPopulator" />
</bean>
<property name="userDetailsContextMapper" ref="userDetailsMapper" />
</bean>
- <bean id="authoritiesPopulator"
- class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
+ <bean id="authoritiesPopulator" class="org.argeo.security.ldap.ArgeoLdapAuthoritiesPopulator">
<constructor-arg ref="contextSource" />
<constructor-arg value="ou=groups" />
<!-- <property name="defaultRole" value="ROLE_USER" /> -->
interface="org.springframework.security.AuthenticationManager" />\r
\r
<service ref="userDao" interface="org.argeo.security.dao.UserDao" />\r
+ <service ref="roleDao" interface="org.argeo.security.dao.RoleDao" />\r
</beans:beans>
\ No newline at end of file
Import-Package: javax.servlet,
javax.servlet.http,
javax.servlet.resources,
+ org.argeo.security.dao,
org.argeo.security.mvc,
- org.argeo.server.json.mvc,
+ org.argeo.server.json,
+ org.argeo.server.mvc,
org.springframework.ldap.core.support,
org.springframework.osgi.web.context.support,
org.springframework.security,
org.springframework.web.context,
org.springframework.web.context.support,
org.springframework.web.filter,
- org.springframework.web.servlet,
- org.argeo.security.dao
+ org.springframework.web.servlet
Web-ContextPath: org.argeo.security.webapp
interface="org.springframework.security.AuthenticationManager" />\r
\r
<reference id="userDao" interface="org.argeo.security.dao.UserDao" />\r
+ <reference id="roleDao" interface="org.argeo.security.dao.RoleDao" />\r
\r
</beans:beans>
\ No newline at end of file
<bean id="controller" class="org.argeo.security.mvc.UsersRolesController">
<property name="userDao" ref="userDao" />
+ <property name="roleDao" ref="roleDao" />
</bean>
- <bean id="viewResolver" class="org.argeo.server.json.mvc.JsonViewResolver">
+ <bean id="viewResolver" class="org.argeo.server.mvc.SerializingViewResolver">
+ <property name="serializer" ref="serverMapper" />
</bean>
+ <bean id="serverMapper" class="org.argeo.server.json.JsonServerMapper">
+ </bean>
+
+ <bean class="org.argeo.server.mvc.DefaultHandlerExceptionResolver" />
+
</beans>
\ No newline at end of file
import java.util.List;
-import org.argeo.security.ArgeoUser;
-
public interface RoleDao {
- public List<String> listRoles();
+ public List<String> listEditableRoles();
public void create(String role);
- public List<String> listUserRoles(ArgeoUser user);
+ public void delete(String role);
+
}
public void update(ArgeoUser user);
public void delete(String username);
-
+
public void updatePassword(String oldPassword, String newPassword);
-
+
public Boolean userExists(String username);
- public ArgeoUser getUser(String uname);
+ public ArgeoUser getUser(String username);
+
+ public void addRoles(String username, List<String> roles);
+
+ public void removeRoles(String username, List<String> roles);
}
--- /dev/null
+package org.argeo.security.ldap;
+
+import org.springframework.ldap.core.ContextSource;
+import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator;
+
+/** TODO: notify Spring Security to open this class more. */
+public class ArgeoLdapAuthoritiesPopulator extends
+ DefaultLdapAuthoritiesPopulator {
+
+ /* Hacked from parent class */
+ private String groupRoleAttribute = "cn";
+ private final String groupSearchBase;
+ private String rolePrefix = "ROLE_";
+ private boolean convertToUpperCase = true;
+
+ public ArgeoLdapAuthoritiesPopulator(ContextSource contextSource,
+ String groupSearchBase) {
+ super(contextSource, groupSearchBase);
+ this.groupSearchBase = groupSearchBase;
+ }
+
+ @Override
+ public void setConvertToUpperCase(boolean convertToUpperCase) {
+ super.setConvertToUpperCase(convertToUpperCase);
+ this.convertToUpperCase = convertToUpperCase;
+ }
+
+ @Override
+ public void setGroupRoleAttribute(String groupRoleAttribute) {
+ super.setGroupRoleAttribute(groupRoleAttribute);
+ this.groupRoleAttribute = groupRoleAttribute;
+ }
+
+ @Override
+ public void setRolePrefix(String rolePrefix) {
+ super.setRolePrefix(rolePrefix);
+ this.rolePrefix = rolePrefix;
+ }
+
+ /** Hacked from parent class. */
+ public String convertGroupToRole(String groupName) {
+ if (convertToUpperCase) {
+ groupName = groupName.toUpperCase();
+ }
+
+ return rolePrefix + groupName;
+ }
+
+ public String getGroupRoleAttribute() {
+ return groupRoleAttribute;
+ }
+
+ public String getGroupSearchBase() {
+ return groupSearchBase;
+ }
+
+}
--- /dev/null
+package org.argeo.security.ldap;
+
+import java.util.List;
+
+import javax.naming.Name;
+
+import org.argeo.security.dao.RoleDao;
+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;
+
+public class RoleDaoLdap implements RoleDao {
+
+ private ArgeoLdapAuthoritiesPopulator authoritiesPopulator;
+ private final LdapTemplate ldapTemplate;
+
+ public RoleDaoLdap(ContextSource contextSource) {
+ ldapTemplate = new LdapTemplate(contextSource);
+ }
+
+ public void create(String role) {
+ Name dn = buildDn(role);
+ DirContextAdapter context = new DirContextAdapter();
+ context.setAttributeValues("objectClass", new String[] { "top",
+ "groupOfUniqueNames" });
+ context.setAttributeValue("cn", role);
+ ldapTemplate.bind(dn, context, null);
+ }
+
+ @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 delete(String role) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setAuthoritiesPopulator(
+ ArgeoLdapAuthoritiesPopulator ldapAuthoritiesPopulator) {
+ this.authoritiesPopulator = ldapAuthoritiesPopulator;
+ }
+
+ protected Name buildDn(String name) {
+ return new DistinguishedName("cn=" + name + ","
+ + authoritiesPopulator.getGroupSearchBase());
+ }
+
+}
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
-import javax.naming.NamingException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.argeo.security.ArgeoUser;
-import org.argeo.security.BasicArgeoUser;
import org.argeo.security.core.ArgeoUserDetails;
import org.argeo.security.dao.UserDao;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
-import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator;
+import org.springframework.security.GrantedAuthority;
+import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsManager;
public class UserDaoLdap implements UserDao {
- private final static Log log = LogFactory.getLog(UserDaoLdap.class);
+ // private final static Log log = LogFactory.getLog(UserDaoLdap.class);
private UserDetailsManager userDetailsManager;
- private DefaultLdapAuthoritiesPopulator authoritiesPopulator;
private String userBase = "ou=users";
+ private String usernameAttribute = "uid";
private final LdapTemplate ldapTemplate;
}
public void create(ArgeoUser user) {
- userDetailsManager.createUser((UserDetails) user);
+ userDetailsManager.createUser(new ArgeoUserDetails(user));
}
public ArgeoUser getUser(String uname) {
@SuppressWarnings("unchecked")
public List<ArgeoUser> listUsers() {
List<String> usernames = (List<String>) ldapTemplate.listBindings(
- new DistinguishedName(userBase), new UserContextMapper());
+ 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
return userDetailsManager.userExists(username);
}
- public void setUserDetailsManager(UserDetailsManager userDetailsManager) {
- this.userDetailsManager = userDetailsManager;
+ public void addRoles(String username, List<String> roles) {
+ GrantedAuthority[] auths = new GrantedAuthority[roles.size()];
+ for (int i = 0; i < roles.size(); i++)
+ auths[i] = new GrantedAuthorityImpl(roles.get(i));
+ ArgeoUserDetails user = (ArgeoUserDetails) userDetailsManager
+ .loadUserByUsername(username);
+ throw new UnsupportedOperationException();
+ //userDetailsManager.
+ }
+
+ public void removeRoles(String username, List<String> roles) {
+ throw new UnsupportedOperationException();
}
- public void setAuthoritiesPopulator(
- DefaultLdapAuthoritiesPopulator authoritiesPopulator) {
- this.authoritiesPopulator = authoritiesPopulator;
+ public void setUserDetailsManager(UserDetailsManager userDetailsManager) {
+ this.userDetailsManager = userDetailsManager;
}
public void setUserBase(String userBase) {
this.userBase = userBase;
}
- class UserContextMapper implements ContextMapper {
- public Object mapFromContext(Object ctxArg) {
- DirContextAdapter ctx = (DirContextAdapter) ctxArg;
- // BasicArgeoUser user = new BasicArgeoUser();
- return ctx.getStringAttribute("uid");
-
- // log.debug("dn# " + ctx.getDn());
- // log.debug("NameInNamespace# " + ctx.getNameInNamespace());
- // log.debug("toString# " + ctx.toString());
-
- // Set<String> roles = authoritiesPopulator.getGroupMembershipRoles(
- // ctx.composeName(user.getUsername(), userBase), user
- // .getUsername());
- // user.setRoles(new ArrayList<String>(roles));
- // GrantedAuthority[] auths = authoritiesPopulator
- // .getGrantedAuthorities(ldapTemplate.,
- // user.getUsername());
- // for (GrantedAuthority auth : auths) {
- // user.getRoles().add(auth.getAuthority());
- // }
- // return user;
- }
+ public void setUsernameAttribute(String usernameAttribute) {
+ this.usernameAttribute = usernameAttribute;
}
-
}
import org.argeo.security.dao.UserDao;
import org.argeo.server.BooleanAnswer;
import org.argeo.server.ServerAnswer;
+import org.argeo.server.mvc.MvcConstants;
import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
-public class UsersRolesController {
+public class UsersRolesController implements MvcConstants {
private UserDao userDao;
private RoleDao roleDao;
+ /* USER */
+
@RequestMapping("/getCredentials.security")
- @ModelAttribute("getCredentials")
+ @ModelAttribute(ANSWER_MODEL_KEY)
public ArgeoUser getCredentials() {
Authentication authentication = SecurityContextHolder.getContext()
.getAuthentication();
-
return ArgeoUserDetails.asArgeoUser(authentication);
}
@RequestMapping("/getUsersList.security")
- @ModelAttribute("getUsersList")
+ @ModelAttribute(ANSWER_MODEL_KEY)
public List<ArgeoUser> getUsersList() {
return userDao.listUsers();
}
@RequestMapping("/userExists.security")
- @ModelAttribute("userExists")
+ @ModelAttribute(ANSWER_MODEL_KEY)
public BooleanAnswer userExists(@RequestParam("username") String username) {
return new BooleanAnswer(userDao.userExists(username));
}
@RequestMapping("/deleteUser.security")
- @ModelAttribute("deleteUser")
+ @ModelAttribute(ANSWER_MODEL_KEY)
public ServerAnswer deleteUser(@RequestParam("username") String username) {
userDao.delete(username);
- return ServerAnswer.ok(username + " deleted");
+ return ServerAnswer.ok("User " + username + " deleted");
}
@RequestMapping("/getUserDetails.security")
- @ModelAttribute("getUserDetails")
+ @ModelAttribute(ANSWER_MODEL_KEY)
public ArgeoUser getUserDetails(@RequestParam("username") String username) {
return userDao.getUser(username);
}
+ /* ROLE */
+ @RequestMapping("/getRolesList.security")
+ @ModelAttribute(ANSWER_MODEL_KEY)
+ public List<String> getEditableRolesList() {
+ return roleDao.listEditableRoles();
+ }
+
+ @RequestMapping("/createRole.security")
+ @ModelAttribute(ANSWER_MODEL_KEY)
+ public ServerAnswer createRole(@RequestParam("role") String role) {
+ roleDao.create(role);
+ return ServerAnswer.ok("Role " + role + " created");
+ }
+
+ @RequestMapping("/deleteRole.security")
+ @ModelAttribute(ANSWER_MODEL_KEY)
+ public ServerAnswer deleteRole(@RequestParam("role") String role) {
+ roleDao.delete(role);
+ return ServerAnswer.ok("Role " + role + " created");
+ }
+
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
--- /dev/null
+package org.argeo.server;
+
+import javax.servlet.http.HttpServletRequest;
+
+public interface ServerDeserializer {
+ public Object deserialize(Object obj, HttpServletRequest request);
+}
--- /dev/null
+package org.argeo.server;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public interface ServerSerializer {
+ public void serialize(Object obj, HttpServletRequest request,
+ HttpServletResponse response);
+}
--- /dev/null
+package org.argeo.server.mvc;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.argeo.server.ServerAnswer;
+import org.springframework.web.servlet.HandlerExceptionResolver;
+import org.springframework.web.servlet.ModelAndView;
+
+public class DefaultHandlerExceptionResolver implements
+ HandlerExceptionResolver {
+
+ public ModelAndView resolveException(HttpServletRequest request,
+ HttpServletResponse response, Object handler, Exception ex) {
+ ModelAndView mv = new ModelAndView();
+ mv.addObject(ServerAnswer.error(ex));
+ return mv;
+ }
+
+}
--- /dev/null
+package org.argeo.server.mvc;
+
+public interface MvcConstants {
+ public final static String ANSWER_MODEL_KEY = "org.argeo.server.mvc.ANSWER";
+}
--- /dev/null
+package org.argeo.server.mvc;
+
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.argeo.server.ArgeoServerException;
+import org.argeo.server.ServerSerializer;
+import org.springframework.web.servlet.view.AbstractView;
+
+public class SerializingView extends AbstractView implements MvcConstants {
+ private final String viewName;
+ private final Locale locale;
+
+ private final ServerSerializer serializer;
+
+ public SerializingView(String viewName, Locale locale,
+ ServerSerializer serializer) {
+ this.viewName = viewName;
+ this.locale = locale;
+ this.serializer = serializer;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void renderMergedOutputModel(Map model,
+ HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+ final Object answer;
+ if (model.size() == 1) {
+ answer = model.values().iterator().next();
+ } else if (model.containsKey(ANSWER_MODEL_KEY)) {
+ answer = model.get(ANSWER_MODEL_KEY);
+ } else if (model.containsKey(viewName)) {
+ answer = model.get(viewName);
+ } else {
+ throw new ArgeoServerException(
+ "Model has a size different from 1. Specify a modelKey.");
+ }
+
+ serializer.serialize(answer, request, response);
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+
+ public Locale getLocale() {
+ return locale;
+ }
+
+}
--- /dev/null
+package org.argeo.server.mvc;
+
+import java.util.Locale;
+
+import org.argeo.server.ServerSerializer;
+import org.springframework.web.servlet.View;
+import org.springframework.web.servlet.view.AbstractCachingViewResolver;
+
+/**
+ * Returns a {@link SerializingView} based on the underlying.
+ */
+public class SerializingViewResolver extends AbstractCachingViewResolver {
+ private ServerSerializer serializer;
+
+ @Override
+ protected View loadView(String viewName, Locale locale) throws Exception {
+ return new SerializingView(viewName, locale, serializer);
+ }
+
+ public void setSerializer(ServerSerializer serializer) {
+ this.serializer = serializer;
+ }
+
+}
--- /dev/null
+package org.argeo.server.json;
+
+import java.io.BufferedReader;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.argeo.server.ArgeoServerException;
+import org.argeo.server.ServerDeserializer;
+import org.argeo.server.ServerSerializer;
+import org.codehaus.jackson.JsonFactory;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.map.ObjectMapper;
+
+public class JsonServerMapper implements ServerSerializer, ServerDeserializer {
+ private JsonFactory jsonFactory = new JsonFactory();
+ private ObjectMapper objectMapper = new ObjectMapper();
+
+ public void serialize(Object obj, HttpServletRequest request,
+ HttpServletResponse response) {
+ try {
+ response.setContentType("application/json");
+
+ JsonGenerator jsonGenerator = jsonFactory
+ .createJsonGenerator(response.getWriter());
+ jsonGenerator.useDefaultPrettyPrinter();
+
+ objectMapper.writeValue(jsonGenerator, obj);
+ } catch (Exception e) {
+ throw new ArgeoServerException("Cannot serialize " + obj, e);
+ }
+ }
+
+ public Object deserialize(Object obj, HttpServletRequest request) {
+ try {
+ String body = request.getParameter("body");
+ if (body == null) {
+ // lets read the message body instead
+ BufferedReader reader = request.getReader();
+ StringBuffer buffer = new StringBuffer();
+ String line = null;
+ while (((line = reader.readLine()) != null)) {
+ buffer.append(line);
+ }
+ body = buffer.toString();
+ }
+ return objectMapper.readValue(body, Object.class);
+ } catch (Exception e) {
+ throw new ArgeoServerException("Cannot deserialize " + request, e);
+ }
+ }
+
+}
+++ /dev/null
-package org.argeo.server.json.mvc;
-
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.argeo.server.ArgeoServerException;
-import org.codehaus.jackson.JsonFactory;
-import org.codehaus.jackson.JsonGenerator;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.springframework.web.servlet.view.AbstractView;
-
-/** Marshal one of the object of the map to the output. */
-public class JsonView extends AbstractView {
- private JsonFactory jsonFactory = new JsonFactory();
- private ObjectMapper objectMapper = new ObjectMapper();
-
- private String modelKey = null;
-
- public JsonView(String modelKey) {
- this.modelKey = modelKey;
- }
-
- @Override
- @SuppressWarnings(value = { "unchecked" })
- protected void renderMergedOutputModel(Map model,
- HttpServletRequest request, HttpServletResponse response)
- throws Exception {
- final Object answer;
- if (model.size() == 1)
- answer = model.values().iterator().next();
- else if (modelKey != null) {
- if (!model.containsKey(modelKey))
- throw new ArgeoServerException("Key " + modelKey
- + " not found in model.");
- answer = model.get(modelKey);
- } else {// models.size!=1 and no modelKey
- throw new ArgeoServerException(
- "Model has a size different from 1. Specify a modelKey.");
- }
-
- response.setContentType("application/json");
-
- JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(response
- .getWriter());
- jsonGenerator.useDefaultPrettyPrinter();
-
- objectMapper.writeValue(jsonGenerator, answer);
-
- }
-
- public void setModelKey(String modelKey) {
- this.modelKey = modelKey;
- }
-
-}
+++ /dev/null
-package org.argeo.server.json.mvc;
-
-import java.util.Locale;
-
-import org.springframework.web.servlet.View;
-import org.springframework.web.servlet.view.AbstractCachingViewResolver;
-
-/**
- * Returns a {@link JsonView} based on the underlying. View name is the model
- * key of the JSON view.
- */
-public class JsonViewResolver extends AbstractCachingViewResolver {
- @Override
- protected View loadView(String viewName, Locale locale) throws Exception {
- return new JsonView(viewName);
- }
-
-}