You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rave.apache.org by ja...@apache.org on 2011/10/19 16:32:01 UTC

svn commit: r1186239 - in /incubator/rave/trunk: rave-components/rave-core/src/main/java/org/apache/rave/portal/model/ rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/ rave-components/rave-core/src/main/java/org/apache/rave/po...

Author: jasha
Date: Wed Oct 19 14:32:00 2011
New Revision: 1186239

URL: http://svn.apache.org/viewvc?rev=1186239&view=rev
Log:
RAVE-300 update user authorities

Added:
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/AuthorityService.java
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultAuthorityService.java
    incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/DefaultAuthorityServiceTest.java
Modified:
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/Authority.java
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/User.java
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/AuthorityRepository.java
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/impl/JpaAuthorityRepository.java
    incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/model/AuthorityTest.java
    incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/repository/JpaAuthorityRepositoryTest.java
    incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/UserServiceTest.java
    incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/admin/UserController.java
    incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/admin/UserControllerTest.java
    incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/admin/userdetail.jsp
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css

Modified: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/Authority.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/Authority.java?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/Authority.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/Authority.java Wed Oct 19 14:32:00 2011
@@ -45,14 +45,18 @@ import java.util.Collection;
 @Entity
 @Table(name = "granted_authority")
 @NamedQueries({
-        @NamedQuery(name = Authority.GET_BY_AUTHORITY_NAME, query = "SELECT a FROM Authority a WHERE a.authority = :authority")
+        @NamedQuery(name = Authority.GET_BY_AUTHORITY_NAME, query = "SELECT a FROM Authority a WHERE a.authority = :authority"),
+        @NamedQuery(name = Authority.GET_ALL, query = "SELECT a FROM Authority a"),
+        @NamedQuery(name = Authority.COUNT_ALL, query = "SELECT COUNT(a) FROM Authority a")
 })
 public class Authority implements GrantedAuthority, BasicEntity, Serializable {
 
-    private static final long serialVersionUID = -3946689281908099905L;
+    private static final long serialVersionUID = 463209366149842862L;
 
     public static final String PARAM_AUTHORITY_NAME = "authority";
     public static final String GET_BY_AUTHORITY_NAME = "Authority.GetByAuthorityName";
+    public static final String GET_ALL = "Authority.GetAll";
+    public static final String COUNT_ALL = "Authority.CountAll";
 
     @Id
     @Column(name = "entity_id")
@@ -73,17 +77,6 @@ public class Authority implements Grante
      * Default constructor, needed for JPA
      */
     public Authority() {
-        this(null);
-    }
-
-    /**
-     * Utility constructor
-     *
-     * @param authority (unique) name of the authority (role)
-     */
-    public Authority(String authority) {
-        super();
-        this.authority = authority;
         this.users = new ArrayList<User>();
     }
 
@@ -132,4 +125,29 @@ public class Authority implements Grante
         }
         this.users = null;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        Authority authority = (Authority) o;
+
+        if (entityId != null ? !entityId.equals(authority.entityId) : authority.entityId != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return entityId != null ? entityId.hashCode() : 0;
+    }
+
 }

Modified: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/User.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/User.java?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/User.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/User.java Wed Oct 19 14:32:00 2011
@@ -173,6 +173,9 @@ public class User implements UserDetails
         }
     }
 
+    public void setAuthorities(Collection<Authority> newAuthorities) {
+        this.authorities = newAuthorities;
+    }
 
     //TODO RAVE-233:Setup Hashing and Salting of Passwords
 

Modified: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/AuthorityRepository.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/AuthorityRepository.java?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/AuthorityRepository.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/AuthorityRepository.java Wed Oct 19 14:32:00 2011
@@ -22,6 +22,8 @@ package org.apache.rave.portal.repositor
 import org.apache.rave.persistence.Repository;
 import org.apache.rave.portal.model.Authority;
 
+import java.util.List;
+
 /**
  * Repository interface for {@link org.apache.rave.portal.model.Authority}
  */
@@ -34,4 +36,14 @@ public interface AuthorityRepository ext
      * @return Authority if it can be found, otherwise {@literal null}
      */
     Authority getByAuthority(String authorityName);
+
+    /**
+     * @return a List of all {@link Authority}'s.
+     */
+    List<Authority> getAll();
+
+    /**
+     * @return the total number of authorities in the repository
+     */
+    int getCountAll();
 }

Modified: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/impl/JpaAuthorityRepository.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/impl/JpaAuthorityRepository.java?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/impl/JpaAuthorityRepository.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/impl/JpaAuthorityRepository.java Wed Oct 19 14:32:00 2011
@@ -24,7 +24,9 @@ import org.apache.rave.portal.model.Auth
 import org.apache.rave.portal.repository.AuthorityRepository;
 import org.springframework.stereotype.Repository;
 
+import javax.persistence.Query;
 import javax.persistence.TypedQuery;
+import java.util.List;
 
 import static org.apache.rave.persistence.jpa.util.JpaUtil.getSingleResult;
 
@@ -45,4 +47,17 @@ public class JpaAuthorityRepository exte
         query.setParameter(Authority.PARAM_AUTHORITY_NAME, authorityName);
         return getSingleResult(query.getResultList());
     }
+
+    @Override
+    public List<Authority> getAll() {
+        TypedQuery<Authority> query = manager.createNamedQuery(Authority.GET_ALL, Authority.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public int getCountAll() {
+        Query query = manager.createNamedQuery(Authority.COUNT_ALL);
+        Number countResult = (Number) query.getSingleResult();
+        return countResult.intValue();
+    }
 }

Added: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/AuthorityService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/AuthorityService.java?rev=1186239&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/AuthorityService.java (added)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/AuthorityService.java Wed Oct 19 14:32:00 2011
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.rave.portal.service;
+
+import org.apache.rave.portal.model.Authority;
+import org.apache.rave.portal.model.util.SearchResult;
+
+public interface AuthorityService {
+
+    /**
+     * @param entityId unique identifier of the {@link Authority}
+     * @return Authority if it can be found, otherwise {@literal null}
+     */
+    Authority getAuthorityById(long entityId);
+
+    /**
+     * @param authorityName name of the authority, can be a role (ROLE_USER)
+     * @return Authority if it can be found, otherwise {@literal null}
+     */
+    Authority getAuthorityByName(String authorityName);
+
+    /**
+     * @return a {@link SearchResult} with all {@link Authority}'s
+     */
+    SearchResult<Authority> getAllAuthorities();
+}

Added: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultAuthorityService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultAuthorityService.java?rev=1186239&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultAuthorityService.java (added)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultAuthorityService.java Wed Oct 19 14:32:00 2011
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.rave.portal.service.impl;
+
+import org.apache.rave.portal.model.Authority;
+import org.apache.rave.portal.model.util.SearchResult;
+import org.apache.rave.portal.repository.AuthorityRepository;
+import org.apache.rave.portal.service.AuthorityService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class DefaultAuthorityService implements AuthorityService {
+
+
+    private final AuthorityRepository repository;
+
+    @Autowired
+    public DefaultAuthorityService(AuthorityRepository repository) {
+        this.repository = repository;
+    }
+
+    @Override
+    public Authority getAuthorityById(long entityId) {
+        return repository.get(entityId);
+    }
+
+    @Override
+    public Authority getAuthorityByName(String authorityName) {
+        return repository.getByAuthority(authorityName);
+    }
+
+    @Override
+    public SearchResult<Authority> getAllAuthorities() {
+        final int count = repository.getCountAll();
+        final List<Authority> authorities = repository.getAll();
+        return new SearchResult<Authority>(authorities, count);
+    }
+}

Modified: incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/model/AuthorityTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/model/AuthorityTest.java?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/model/AuthorityTest.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/model/AuthorityTest.java Wed Oct 19 14:32:00 2011
@@ -35,7 +35,5 @@ public class AuthorityTest {
         ((Authority) grantedAuthority).setAuthority("user");
         assertEquals("user", grantedAuthority.getAuthority());
 
-        GrantedAuthority grantedAuthority2 = new Authority("admin");
-        assertEquals("admin", grantedAuthority2.getAuthority());
     }
 }

Modified: incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/repository/JpaAuthorityRepositoryTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/repository/JpaAuthorityRepositoryTest.java?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/repository/JpaAuthorityRepositoryTest.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/repository/JpaAuthorityRepositoryTest.java Wed Oct 19 14:32:00 2011
@@ -31,8 +31,10 @@ import org.springframework.transaction.a
 
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
+import java.util.List;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
@@ -93,7 +95,8 @@ public class JpaAuthorityRepositoryTest 
     @Test
     public void addOrDeleteAuthorityDoesNotAffectUser() {
         final String authorityName = "guest";
-        Authority authority = new Authority(authorityName);
+        Authority authority = new Authority();
+        authority.setAuthority(authorityName);
         User user = userRepository.get(1L);
 
         Assert.assertNotNull("User is not null", user);
@@ -116,4 +119,16 @@ public class JpaAuthorityRepositoryTest 
         Assert.assertNotNull("User should not be deleted after removing an authority", user);
         Assert.assertTrue("User should have no authorities", user.getAuthorities().isEmpty());
     }
+
+    @Test
+    public void getAll() {
+        List<Authority> allAuthorities = repository.getAll();
+        assertFalse("Found authorities", allAuthorities.isEmpty());
+    }
+
+    @Test
+    public void countAll() {
+        int numberOfAuthorities = repository.getCountAll();
+        assertTrue("Found at least 1 Authority", numberOfAuthorities > 0);
+    }
 }

Added: incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/DefaultAuthorityServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/DefaultAuthorityServiceTest.java?rev=1186239&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/DefaultAuthorityServiceTest.java (added)
+++ incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/DefaultAuthorityServiceTest.java Wed Oct 19 14:32:00 2011
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.rave.portal.service;
+
+import org.apache.rave.portal.model.Authority;
+import org.apache.rave.portal.model.util.SearchResult;
+import org.apache.rave.portal.repository.AuthorityRepository;
+import org.apache.rave.portal.service.impl.DefaultAuthorityService;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+Test for {@link org.apache.rave.portal.service.impl.DefaultAuthorityService}
+ */
+public class DefaultAuthorityServiceTest {
+
+    private AuthorityService service;
+    private AuthorityRepository repository;
+
+    @Before
+    public void setup() {
+        repository = createMock(AuthorityRepository.class);
+        service = new DefaultAuthorityService(repository);
+    }
+
+    @Test
+    public void getAuthorityById() {
+        Authority authority = createAuthority();
+
+        expect(repository.get(123L)).andReturn(authority);
+        replay(repository);
+        Authority sAuthority = service.getAuthorityById(123L);
+        assertEquals(sAuthority, authority);
+
+        verify(repository);
+    }
+
+    @Test
+    public void getAuthorityByName() {
+        Authority authority = createAuthority();
+
+        expect(repository.getByAuthority("FOO")).andReturn(authority);
+        replay(repository);
+        Authority sAuthority = service.getAuthorityByName("FOO");
+        assertEquals(sAuthority, authority);
+
+        verify(repository);
+
+    }
+
+    private static Authority createAuthority() {
+        Authority authority = new Authority();
+        authority.setAuthority("FOO");
+        final long entityId = 123L;
+        authority.setEntityId(entityId);
+        return authority;
+    }
+
+    @Test
+    public void getAuthorityById_NotFound() {
+        Authority authority = new Authority();
+        authority.setAuthority("BAR");
+        final long entityId = 456L;
+        authority.setEntityId(entityId);
+
+        expect(repository.get(entityId)).andReturn(null);
+        replay(repository);
+        Authority sAuthority = service.getAuthorityById(entityId);
+        assertNull(sAuthority);
+
+        verify(repository);
+    }
+
+    @Test
+    public void allAuthorities() {
+        List<Authority> authorities = new ArrayList<Authority>();
+        Authority foo = new Authority();
+        foo.setAuthority("FOO");
+        Authority bar = new Authority();
+        bar.setAuthority("BAR");
+        authorities.add(foo);
+        authorities.add(bar);
+
+        expect(repository.getAll()).andReturn(authorities);
+        expect(repository.getCountAll()).andReturn(authorities.size());
+        replay(repository);
+        SearchResult<Authority> allAuthorities = service.getAllAuthorities();
+        verify(repository);
+
+        assertEquals(2, allAuthorities.getTotalResults());
+        assertEquals(2, allAuthorities.getResultSet().size());
+    }
+}

Modified: incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/UserServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/UserServiceTest.java?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/UserServiceTest.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/UserServiceTest.java Wed Oct 19 14:32:00 2011
@@ -118,7 +118,8 @@ public class UserServiceTest {
     @Test
     public void setAuthenticatedUser_validRole() {
         final User authUser = new User(USER_ID);
-        final Authority userRole = new Authority("admin");
+        final Authority userRole = new Authority();
+        userRole.setAuthority("admin");
         authUser.addAuthority(userRole);
         expect(repository.get(USER_ID)).andReturn(authUser).anyTimes();
         replay(repository);

Modified: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/admin/UserController.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/admin/UserController.java?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/admin/UserController.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/admin/UserController.java Wed Oct 19 14:32:00 2011
@@ -19,8 +19,10 @@
 
 package org.apache.rave.portal.web.controller.admin;
 
+import org.apache.rave.portal.model.Authority;
 import org.apache.rave.portal.model.User;
 import org.apache.rave.portal.model.util.SearchResult;
+import org.apache.rave.portal.service.AuthorityService;
 import org.apache.rave.portal.service.UserService;
 import org.apache.rave.portal.web.util.ModelKeys;
 import org.apache.rave.portal.web.util.ViewNames;
@@ -29,6 +31,8 @@ import org.springframework.beans.factory
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
 import org.springframework.web.bind.annotation.ModelAttribute;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -36,6 +40,9 @@ import org.springframework.web.bind.anno
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.SessionAttributes;
 
+import java.beans.PropertyEditorSupport;
+import java.security.Principal;
+
 /**
  * Admin controller to manipulate User data
  */
@@ -43,15 +50,25 @@ import org.springframework.web.bind.anno
 @SessionAttributes({"user"})
 public class UserController {
 
+    private static final String SELECTED_ITEM = "users";
+
     @Autowired
     private UserService userService;
 
     @Autowired
+    private AuthorityService authorityService;
+
+    @Autowired
     private UserProfileValidator userProfileValidator;
 
+    @InitBinder
+    public void initBinder(WebDataBinder b) {
+        b.registerCustomEditor(Authority.class, new AuthorityEditor());
+    }
+
     @RequestMapping(value = "/admin/users", method = RequestMethod.GET)
     public String viewUsers(@RequestParam(required = false, defaultValue = "0") int offset, Model model) {
-        AdminControllerUtil.addNavigationMenusToModel("users", model);
+        AdminControllerUtil.addNavigationMenusToModel(SELECTED_ITEM, model);
         final SearchResult<User> users = userService.getLimitedListOfUsers(offset, AdminControllerUtil.DEFAULT_PAGE_SIZE);
         model.addAttribute(ModelKeys.SEARCHRESULT, users);
         return ViewNames.ADMIN_USERS;
@@ -60,7 +77,7 @@ public class UserController {
     @RequestMapping(value = "/admin/users/search", method = RequestMethod.GET)
     public String searchUsers(@RequestParam(required = true) String searchTerm,
                               @RequestParam(required = false, defaultValue = "0") int offset, Model model) {
-        AdminControllerUtil.addNavigationMenusToModel("users", model);
+        AdminControllerUtil.addNavigationMenusToModel(SELECTED_ITEM, model);
         final SearchResult<User> users = userService.getUsersByFreeTextSearch(
                 searchTerm, offset, AdminControllerUtil.DEFAULT_PAGE_SIZE);
         model.addAttribute(ModelKeys.SEARCH_TERM, searchTerm);
@@ -69,29 +86,55 @@ public class UserController {
     }
 
     @RequestMapping(value = "/admin/userdetail/{userid}", method = RequestMethod.GET)
-    public String viewUserDetail(@PathVariable("userid") Long userid, Model model) {
-        AdminControllerUtil.addNavigationMenusToModel("users", model);
-        final User user = userService.getUserById(userid);
-        model.addAttribute(user);
+    public String viewUserDetail(@PathVariable("userid") Long userid, Model model, Principal principal) {
+        AdminControllerUtil.addNavigationMenusToModel(SELECTED_ITEM, model);
+        model.addAttribute(userService.getUserById(userid));
+        model.addAttribute("loggedInUser", principal.getName());
         return ViewNames.ADMIN_USERDETAIL;
     }
 
     @RequestMapping(value = "/admin/userdetail/update", method = RequestMethod.POST)
-    public String updateUserDetail(@ModelAttribute("user") User user, BindingResult result) {
+    public String updateUserDetail(@ModelAttribute("user") User user, BindingResult result,
+                                   Model model, Principal principal) {
         userProfileValidator.validate(user, result);
         if (result.hasErrors()) {
+            model.addAttribute("loggedInUser", principal.getName());
             return ViewNames.ADMIN_USERDETAIL;
         }
         userService.updateUserProfile(user);
         return "redirect:" + user.getEntityId();
     }
 
+    @ModelAttribute("authorities")
+    public SearchResult<Authority> populateAuthorityList() {
+        return authorityService.getAllAuthorities();
+    }
+
+    // setters for unit tests
     void setUserService(UserService userService) {
         this.userService = userService;
     }
 
+    void setAuthorityService(AuthorityService authorityService) {
+        this.authorityService = authorityService;
+    }
+
     void setUserProfileValidator(UserProfileValidator userProfileValidator) {
         this.userProfileValidator = userProfileValidator;
     }
 
+    /**
+     * Mapping between the submitted form value and an {@link Authority}
+     */
+    private class AuthorityEditor extends PropertyEditorSupport {
+
+        @Override
+        public void setAsText(String text) throws IllegalArgumentException {
+            Authority authority = authorityService.getAuthorityByName(text);
+            setValue(authority);
+        }
+
+    }
+
+
 }

Modified: incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/admin/UserControllerTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/admin/UserControllerTest.java?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/admin/UserControllerTest.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/admin/UserControllerTest.java Wed Oct 19 14:32:00 2011
@@ -19,8 +19,10 @@
 
 package org.apache.rave.portal.web.controller.admin;
 
+import org.apache.rave.portal.model.Authority;
 import org.apache.rave.portal.model.User;
 import org.apache.rave.portal.model.util.SearchResult;
+import org.apache.rave.portal.service.AuthorityService;
 import org.apache.rave.portal.service.UserService;
 import org.apache.rave.portal.web.util.ModelKeys;
 import org.apache.rave.portal.web.util.ViewNames;
@@ -32,15 +34,18 @@ import org.springframework.ui.Model;
 import org.springframework.validation.BeanPropertyBindingResult;
 import org.springframework.validation.BindingResult;
 
+import java.security.Principal;
 import java.util.ArrayList;
 import java.util.List;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
-import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
 
 /**
  * Test for {@link UserController}
@@ -51,6 +56,7 @@ public class UserControllerTest {
 
     private UserController controller;
     private UserService userService;
+    private AuthorityService authorityService;
 
     @Test
     public void adminUsers() throws Exception {
@@ -89,23 +95,29 @@ public class UserControllerTest {
 
 
     @Test
-    public void adminUserDetail() throws Exception {
+    public void viewAdminUserDetail() throws Exception {
         Model model = new ExtendedModelMap();
         Long userid = 123L;
         User user = new User(userid, "john.doe.sr");
+        Principal principal = createMock(Principal.class);
 
+        expect(principal.getName()).andReturn("canonical");
         expect(userService.getUserById(userid)).andReturn(user);
-        replay(userService);
+        replay(userService, principal);
 
-        String adminUserDetailView = controller.viewUserDetail(userid, model);
+        String adminUserDetailView = controller.viewUserDetail(userid, model, principal);
+        verify(userService, principal);
+        
         assertEquals(ViewNames.ADMIN_USERDETAIL, adminUserDetailView);
         assertTrue(model.containsAttribute(TABS));
         assertEquals(user, model.asMap().get("user"));
+        assertEquals("canonical", model.asMap().get("loggedInUser"));
     }
 
 
     @Test
     public void updateUserDetail_success() {
+        Model model = new ExtendedModelMap();
         final Long userid = 123L;
         final String email = "john.doe.sr@example.net";
         User user = new User(userid, "john.doe.sr");
@@ -114,31 +126,57 @@ public class UserControllerTest {
         user.setEmail(email);
         final BindingResult errors = new BeanPropertyBindingResult(user, "user");
 
-        expect(userService.getUserById(userid)).andReturn(user);
+        Principal principal = createMock(Principal.class);
+
         expect(userService.getUserByEmail(email)).andReturn(user);
+        userService.updateUserProfile(user);
+        expectLastCall();
         replay(userService);
-        final String view = controller.updateUserDetail(user, errors);
+
+        final String view = controller.updateUserDetail(user, errors, model, principal);
+        verify(userService);
+
         assertFalse(errors.hasErrors());
         assertEquals("redirect:" + userid, view);
     }
 
     @Test
     public void updateUserDetail_withErrors() {
+        Model model = new ExtendedModelMap();
         Long userid = 123L;
         User user = new User(userid, "john.doe.sr");
         final BindingResult errors = new BeanPropertyBindingResult(user, "user");
-        final String view = controller.updateUserDetail(user, errors);
+        Principal principal = createMock(Principal.class);
+
+        expect(principal.getName()).andReturn("canonical");
+        replay(principal);
+        final String view = controller.updateUserDetail(user, errors, model, principal);
+        verify(principal);
+
         assertTrue(errors.hasErrors());
         assertEquals(ViewNames.ADMIN_USERDETAIL, view);
     }
 
+    @Test
+    public void getAuthoritiesForModelMap() {
+        final SearchResult<Authority> authorities = createSearchResultWithTwoAuthorities();
+        expect(authorityService.getAllAuthorities()).andReturn(authorities);
+        replay(authorityService);
+        final SearchResult<Authority> result = controller.populateAuthorityList();
+        verify(authorityService);
+        assertEquals(authorities, result);
+    }
+
     @Before
     public void setUp() throws Exception {
         controller = new UserController();
 
-        userService = createNiceMock(UserService.class);
+        userService = createMock(UserService.class);
         controller.setUserService(userService);
 
+        authorityService = createMock(AuthorityService.class);
+        controller.setAuthorityService(authorityService);
+
         UserProfileValidator userProfileValidator = new UserProfileValidator(userService);
         controller.setUserProfileValidator(userProfileValidator);
     }
@@ -153,4 +191,15 @@ public class UserControllerTest {
         final int totalResult = 12390;
         return new SearchResult<User>(users, totalResult);
     }
+
+    private static SearchResult<Authority> createSearchResultWithTwoAuthorities() {
+        List<Authority> authorities = new ArrayList<Authority>();
+        Authority foo = new Authority();
+        foo.setAuthority("FOO");
+        Authority bar = new Authority();
+        bar.setAuthority("BAR");
+        authorities.add(foo);
+        authorities.add(bar);
+        return new SearchResult<Authority>(authorities, authorities.size());
+    }
 }

Modified: incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties Wed Oct 19 14:32:00 2011
@@ -116,14 +116,18 @@ admin.widgets.title=Rave admin interface
 admin.widgets.shorttitle=Widgets
 admin.users.title=Rave admin interface - Users
 admin.users.shorttitle=Users
-admin.users.search=Search users
+admin.users.search=Search Users
+admin.users.add=Add user
 admin.userdetail.title=Rave admin interface - User detail
+admin.userdetail.goback=\u00AB Back to users
+admin.userdetail.editdata=Edit user data
 admin.userdata.username=Username
 admin.userdata.email=Email
 admin.userdata.accountstatus=Account status:
 admin.userdata.enabled=Account enabled
 admin.userdata.expired=Account expired
 admin.userdata.locked=Account locked
+admin.userdata.authorities=Authorities:
 admin.clearsearch=Clear search
 
 admin.list.noresult=No results found

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/admin/userdetail.jsp
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/admin/userdetail.jsp?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/admin/userdetail.jsp (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/admin/userdetail.jsp Wed Oct 19 14:32:00 2011
@@ -16,6 +16,7 @@
   specific language governing permissions and limitations
   under the License.
   --%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" %>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
@@ -25,56 +26,90 @@
 <fmt:setBundle basename="messages"/>
 
 <fmt:message key="admin.userdetail.title" var="pagetitle"/>
+
+<c:set var="canChangeUserStatus" value="${user.username ne loggedInUser}"/>
+
 <rave:rave_generic_page pageTitle="${pagetitle}">
     <rave:header pageTitle="${pagetitle}"/>
     <rave:admin_tabsheader/>
     <div id="pageContent">
         <article class="admincontent">
-            <ul class="horizontal-list searchbox">
-                <li><a href="<spring:url value="/app/admin/users"/>">_back to users</a></li>
+            <ul class="horizontal-list goback">
+                <li><a href="<spring:url value="/app/admin/users"/>"><fmt:message key="admin.userdetail.goback"/></a>
+                </li>
             </ul>
             <h2><c:out value="${user.username}"/></h2>
-            <form:form id="updateUserProfile" action="update" commandName="user" method="POST">
-                <form:errors cssClass="error" element="p"/>
-                <fieldset>
-                    <p>
-                        <label for="email"><fmt:message key="page.general.email"/></label>
-                        <spring:bind path="email">
-                            <input type="email" name="email" id="email" value="<c:out value="${status.value}"/>" class="long"/>
-                        </spring:bind>
-                    </p>
-
-                    <p>
-                        <label for="openIdField"><fmt:message key="page.userprofile.openid.url"/></label>
-                        <spring:bind path="openId">
-                            <input type="url" id="openIdField" name="openId" value="<c:out value="${status.value}"/>" class="long"/>
-                        </spring:bind>
-                        <form:errors path="openId" cssClass="error"/>
-                    </p>
-                    <div>
-                        <span class="label"><fmt:message key="admin.userdata.accountstatus"/></span>
-                        <ul class="checkboxlist">
-                            <li>
-                                <fmt:message key="admin.userdata.enabled" var="labelEnabled"/>
-                                <form:checkbox path="enabled" label="${labelEnabled}" />
-                            </li>
-                            <li>
-                                <fmt:message key="admin.userdata.expired" var="labelExpired"/>
-                                <form:checkbox path="expired" label="${labelExpired}"/>
-                            </li>
-                            <li>
-                                <fmt:message key="admin.userdata.locked" var="labelLocked"/>
-                                <form:checkbox path="locked" label="${labelLocked}"/>
-                            </li>
-                        </ul>
-                    </div>
-                </fieldset>
-                <fieldset>
-                    <fmt:message key="page.userprofile.button" var="updateButtonText"/>
-                    <input type="submit" value="${updateButtonText}"/>
-                </fieldset>
-            </form:form>
-            
+
+            <div class="rightcolumn">
+
+            </div>
+
+            <div class="leftcolumn">
+                <section class="formbox">
+                    <h3><fmt:message key="admin.userdetail.editdata"/></h3>
+                    <form:form id="updateUserProfile" action="update" commandName="user" method="POST">
+                        <form:errors cssClass="error" element="p"/>
+                        <fieldset>
+                            <p>
+                                <label for="email"><fmt:message key="page.general.email"/></label>
+                                <spring:bind path="email">
+                                    <input type="email" name="email" id="email" value="<c:out value="${status.value}"/>"
+                                           class="long"/>
+                                </spring:bind>
+                            </p>
+
+                            <p>
+                                <label for="openIdField"><fmt:message key="page.userprofile.openid.url"/></label>
+                                <spring:bind path="openId">
+                                    <input type="url" id="openIdField" name="openId"
+                                           value="<c:out value="${status.value}"/>" class="long"/>
+                                </spring:bind>
+                                <form:errors path="openId" cssClass="error"/>
+                            </p>
+
+                            <div>
+                                <span class="label"><fmt:message key="admin.userdata.accountstatus"/></span>
+                                <ul class="checkboxlist">
+                                    <li>
+                                        <fmt:message key="admin.userdata.enabled" var="labelEnabled"/>
+                                        <form:checkbox path="enabled" label="${labelEnabled}"
+                                                       disabled="${canChangeUserStatus ne true}"/>
+                                    </li>
+                                    <li>
+                                        <fmt:message key="admin.userdata.expired" var="labelExpired"/>
+                                        <form:checkbox path="expired" label="${labelExpired}"
+                                                       disabled="${canChangeUserStatus ne true}"/>
+                                    </li>
+                                    <li>
+                                        <fmt:message key="admin.userdata.locked" var="labelLocked"/>
+                                        <form:checkbox path="locked" label="${labelLocked}"
+                                                       disabled="${canChangeUserStatus ne true}"/>
+                                    </li>
+                                </ul>
+                            </div>
+                        </fieldset>
+                        <fieldset>
+                            <span class="label"><fmt:message key="admin.userdata.authorities"/></span>
+                            <%--@elvariable id="authorities" type="org.apache.rave.portal.model.util.SearchResult<org.apache.rave.portal.model.Authority>"--%>
+                            <ul class="checkboxlist">
+                                <form:checkboxes path="authorities" items="${authorities.resultSet}"
+                                                 itemLabel="authority" itemValue="authority" element="li" />
+                            </ul>
+                        </fieldset>
+                        <fieldset>
+                            <fmt:message key="page.userprofile.button" var="updateButtonText"/>
+                            <input type="submit" value="${updateButtonText}"/>
+                        </fieldset>
+                    </form:form>
+                </section>
+
+            </div>
+
+            <div style="clear:both;">
+
+            </div>
+
+
         </article>
     </div>
 </rave:rave_generic_page>
\ No newline at end of file

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css?rev=1186239&r1=1186238&r2=1186239&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css Wed Oct 19 14:32:00 2011
@@ -633,6 +633,10 @@ span.error, label.error {
     margin-top:1em;
 }
 
+.admincontent .goback {
+    padding-top: 1em;
+}
+
 .searchbox form, .searchbox fieldset {
     display:inline;
     height:1em;
@@ -725,6 +729,22 @@ span.error, label.error {
     text-decoration: underline;
 }
 
+.admincontent .leftcolumn {
+    float:left;
+    width: 70%;
+}
+
+.admincontent .rightcolumn {
+    float:right;
+    width: 30%;
+}
+
+.formbox {
+    border:1px solid #B4C4CF;
+    margin:1em 10px;
+    padding: 0 10px;
+}
+
 .booleancell {
     width: 50px;
 }