rave-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From carlu...@apache.org
Subject svn commit: r1185340 - in /incubator/rave/trunk: rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/ rave-components/rave-core/src/main/java/org/apache/rave/portal/service/ rave-components/rave-core/src/test/java/org/apache/ra...
Date Mon, 17 Oct 2011 19:27:22 GMT
Author: carlucci
Date: Mon Oct 17 19:27:21 2011
New Revision: 1185340

URL: http://svn.apache.org/viewvc?rev=1185340&view=rev
Log:
Changes in support of RAVE-298:
- created common AbstractRestApi class
- updated the DefaultPagePermissionEvaluator to handle permission checks when the object to
be checked differs from the returned Object
- secured remaining PageService methods that deal with Page objects, except addNewDefaultPage
(see RAVE-303)

Added:
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/RaveMethodSecurityExpressionHandler.java
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/RaveSecurityContext.java
    incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/AbstractRestApi.java
    incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rest/AbstractRestApiTest.java
Modified:
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluator.java
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java
    incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluatorTest.java
    incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/PageApi.java
    incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/RegionWidgetApi.java
    incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/WidgetApi.java
    incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rest/PageApiTest.java
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/applicationContext-security.xml

Modified: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluator.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluator.java?rev=1185340&r1=1185339&r2=1185340&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluator.java
(original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluator.java
Mon Oct 17 19:27:21 2011
@@ -77,16 +77,22 @@ public class DefaultPagePermissionEvalua
      * before performing our permission checks.
      * 
      * @param authentication the current Authentication object
-     * @param targetId the entityId of the model to check
+     * @param targetId the entityId of the model to check, or a RaveSecurityContext object
      * @param targetType the class of the model to check
      * @param permission the Permission to check
      * @return true if the Authentication has the proper permission, false otherwise
      */
     @Override
     public boolean hasPermission(Authentication authentication, Serializable targetId, String
targetType, Permission permission) {
-        return hasPermission(authentication, pageRepository.get((Long)targetId), permission,
true);
-    }
-    
+        boolean hasPermission = false;
+        if (targetId instanceof RaveSecurityContext) {
+            hasPermission = verifyRaveSecurityContext(authentication, (RaveSecurityContext)targetId);
          
+        } else {
+            hasPermission = hasPermission(authentication, pageRepository.get((Long)targetId),
permission, true);
+        }
+        return hasPermission;
+    }  
+        
     private boolean hasPermission(Authentication authentication, Page page, Permission permission,
boolean trustedDomainObject) {       
         // this is our container of trusted page objects that can be re-used 
         // in this method so that the same trusted page object doesn't have to
@@ -105,20 +111,11 @@ public class DefaultPagePermissionEvalua
             case ADMINISTER:
                 // if you are here, you are not an administrator, so you can't administer
pages              
                 break;
-            case CREATE:                
-                // anyone can create a page
-                hasPermission = true;
-                break;                
+            case CREATE:                                                                
         
             case DELETE:
-                // users can delete their own page
-                hasPermission = isPageOwner(authentication, page, trustedPageContainer, trustedDomainObject);
               
-                break;
             case READ:
-                // users can read their own page
-                hasPermission = isPageOwner(authentication, page, trustedPageContainer, trustedDomainObject);
    
-                break;
             case UPDATE:
-                // users can update their own page
+                // anyone can create, delete, read, or update a page that they own      
           
                 hasPermission = isPageOwner(authentication, page, trustedPageContainer, trustedDomainObject);
    
                 break;   
             default:
@@ -153,6 +150,30 @@ public class DefaultPagePermissionEvalua
             trustedPage = getTrustedPage(page.getEntityId(), trustedPageContainer);
         }                  
         
-        return ((User)authentication.getPrincipal()).getUsername().equals(trustedPage.getOwner().getUsername());
+        return isPageOwnerByUsername(authentication, trustedPage.getOwner().getUsername());
     }             
+
+    private boolean isPageOwnerByUsername(Authentication authentication, String username)
{
+        return ((User)authentication.getPrincipal()).getUsername().equals(username);
+    }
+    
+    private boolean isPageOwnerById(Authentication authentication, Long userId) {
+        return ((User)authentication.getPrincipal()).getEntityId().equals(userId);
+    }    
+    
+    private boolean verifyRaveSecurityContext(Authentication authentication, RaveSecurityContext
raveSecurityContext) {
+        Class<?> clazz = null;
+        try {
+           clazz = Class.forName(raveSecurityContext.getType());
+        } catch (ClassNotFoundException ex) {
+            throw new IllegalArgumentException("unknown class specified in RaveSecurityContext:
", ex);
+        }
+
+        // perform the permissions check based on the class supplied to the RaveSecurityContext
object
+        if (User.class == clazz) {
+            return isPageOwnerById(authentication, (Long)raveSecurityContext.getId());
+        } else {
+            throw new IllegalArgumentException("unknown RaveSecurityContext type: " + raveSecurityContext.getType());
+        }
+    }   
 }
\ No newline at end of file

Added: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/RaveMethodSecurityExpressionHandler.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/RaveMethodSecurityExpressionHandler.java?rev=1185340&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/RaveMethodSecurityExpressionHandler.java
(added)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/RaveMethodSecurityExpressionHandler.java
Mon Oct 17 19:27:21 2011
@@ -0,0 +1,55 @@
+/*
+ * 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.security.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.Expression;
+import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
+
+/**
+ * Custom DefaultMethodSecurityExpressionHandler class which overrides the
+ * filter method since some JPA implementations will return unmodifiable List
+ * objects.
+ * 
+ * @author carlucci
+ */
+public class RaveMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler
{
+
+    /**
+     * Custom filter method that copies the filterTarget to a modifiable ArrayList
+     * so the containing elements can be filtered out via the parent filter method.
+     * 
+     * @param filterTarget the Collection or array of objects to be filtered
+     * @param filterExpression the filter expression
+     * @param ctx the EvaluationContext
+     * @return the filtered Collection or array
+     */
+    @Override
+    public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext
ctx) {
+        // certain implementations of JPA will create unmodifiable List objects, so clone
the
+        // object into an ArrayList before passing into super.filter                 
+        if (filterTarget instanceof Collection) {
+            return super.filter(new ArrayList((Collection)filterTarget), filterExpression,
ctx);
+        } else {
+            return super.filter(filterTarget, filterExpression, ctx);
+        }                    
+    }    
+}

Added: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/RaveSecurityContext.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/RaveSecurityContext.java?rev=1185340&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/RaveSecurityContext.java
(added)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/RaveSecurityContext.java
Mon Oct 17 19:27:21 2011
@@ -0,0 +1,62 @@
+/*
+ * 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.security.impl;
+
+import java.io.Serializable;
+
+/**
+ * Class used by the Permission security annotations in cases where we want
+ * to perform permission checks on Model objects that are inputs to service 
+ * functions but are not of the same class as the returned object(s).
+ *
+ * For example, verifying that the supplied userId to a function is the 
+ * current authenticated user, when the function returns a List of Page objects.  
+ * See org.apache.rave.portal.service.DefaultPageService.getAllPages for an 
+ * example of usage.
+ * 
+ * @author carlucci
+ */
+public class RaveSecurityContext implements Serializable {
+    // the id of the security context object
+    private Object id;
+    // the type fully qualified class name of the context object
+    private String type;
+
+    public RaveSecurityContext() { }
+    public RaveSecurityContext(Object id, String type) {
+        this.id = id;
+        this.type = type;
+    }
+    
+    public Object getId() {
+        return id;
+    }
+
+    public void setId(Object id) {
+        this.id = id;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+}
\ No newline at end of file

Modified: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java?rev=1185340&r1=1185339&r2=1185340&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java
(original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java
Mon Oct 17 19:27:21 2011
@@ -25,10 +25,19 @@ import org.apache.rave.portal.model.User
 
 import java.util.List;
 import org.springframework.security.access.prepost.PostAuthorize;
+import org.springframework.security.access.prepost.PreAuthorize;
 
 /**
- * TODO the rest of these interface methods need to be annotated with
- * permission security
+ * TODO:
+ * 1) RAVE-303: Protect addNewDefaultPage once the code has been re-factored to call 
+ *    this method from PageController when there are 0 pages for a user instead
+ *    of calling it from DefaultNewAccountService (the user is not authenticated
+ *    at that point)
+ * 
+ * 2) Protect the rest of the non Page object related methods here after writing
+ *    the associated Default<Model>PermissionEvaluator classes.  Also,
+ *    determine if those functions should be re-factored into more appropriate
+ *    service classes
  * 
  * @author carlucci
  */
@@ -47,7 +56,8 @@ public interface PageService {
      *
      * @param userId The user to retrieve pages for.
      * @return A non null possible empty list of pages for the given user.
-     */
+     */   
+    @PreAuthorize("hasPermission(new org.apache.rave.portal.security.impl.RaveSecurityContext(#userId,
'org.apache.rave.portal.model.User'), 'org.apache.rave.portal.model.Page', 'read')") 
     List<Page> getAllPages(long userId);
     
     /**
@@ -66,6 +76,7 @@ public interface PageService {
      * @param pageLayoutCode the page layout code
      * @return the new Page object
      */
+    @PostAuthorize("hasPermission(returnObject, 'create')") 
     Page addNewPage(String pageName, String pageLayoutCode);
     
     /**
@@ -76,7 +87,12 @@ public interface PageService {
      * @param user
      * @param pageLayoutCode
      * @return 
-     */
+     */       
+    // TODO: RAVE-303: addNewDefaultPage is currently not security protected because
+    //       the DefaultPagePermissionEvaluator requires an authenticated user.
+    //       This function should be called in PageController if the user has
+    //       0 pages instead of calling it in DefaultNewAccountService.  Once
+    //       refactored there we can protect this method    
     Page addNewDefaultPage(User user, String pageLayoutCode);
     
     /**
@@ -91,6 +107,7 @@ public interface PageService {
      * 
      * @param pageId the pageId to delete
      */
+    @PreAuthorize("hasPermission(#pageId, 'org.apache.rave.portal.model.Page', 'delete')")

     void deletePage(long pageId);
     
     /**
@@ -136,6 +153,7 @@ public interface PageService {
      * @param name the new name for the page
      * @param pageLayoutCode the new layout for the page
      */
+    @PreAuthorize("hasPermission(#pageId, 'org.apache.rave.portal.model.Page', 'update')")

     Page updatePage(long pageId, String name, String pageLayoutCode);
     
     /**
@@ -146,6 +164,7 @@ public interface PageService {
      *                        -1 if you want this to be the first page
      * @return the updated Page object containing its new render sequence
      */
+    @PreAuthorize("hasPermission(#pageId, 'org.apache.rave.portal.model.Page', 'update')")

     Page movePage(long pageId, long moveAfterPageId);
     
     /**
@@ -154,5 +173,6 @@ public interface PageService {
      * @param pageId the pageId of the page to move to the default position
      * @return the updated Page object containing its new render sequence
      */
+    @PreAuthorize("hasPermission(#pageId, 'org.apache.rave.portal.model.Page', 'update')")

     Page movePageToDefault(long pageId);  
 }
\ No newline at end of file

Modified: incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluatorTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluatorTest.java?rev=1185340&r1=1185339&r2=1185340&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluatorTest.java
(original)
+++ incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluatorTest.java
Mon Oct 17 19:27:21 2011
@@ -48,6 +48,7 @@ public class DefaultPagePermissionEvalua
     private List<GrantedAuthority> grantedAuthoritiesList;
     
     private final Long VALID_PAGE_ID = 3L;
+    private final Long VALID_USER_ID = 99L;
     private final String VALID_USERNAME = "john.doe";
     private final String VALID_USERNAME2 = "jane.doe";
     
@@ -59,6 +60,7 @@ public class DefaultPagePermissionEvalua
         
         user = new User();
         user.setUsername(VALID_USERNAME);
+        user.setEntityId(VALID_USER_ID);
         user2 = new User();
         user2.setUsername(VALID_USERNAME2);
         page = new Page();
@@ -93,14 +95,30 @@ public class DefaultPagePermissionEvalua
     }    
     
     @Test
-    public void testHasPermission_3args_create() {                             
+    public void testHasPermission_3args_create_isPageOwner() {                          
  
         expect(mockAuthentication.getAuthorities()).andReturn(grantedAuthoritiesList);
-        replay(mockAuthentication);      
+        expect(mockAuthentication.getPrincipal()).andReturn(user);
+        expect(mockPageRepository.get(VALID_PAGE_ID)).andReturn(page);
+        replay(mockAuthentication); 
+        replay(mockPageRepository);
         assertThat(defaultPagePermissionEvaluator.hasPermission(mockAuthentication, page,
Permission.CREATE), is(true));        
         verify(mockAuthentication);
+        verify(mockPageRepository);
     }    
     
     @Test
+    public void testHasPermission_3args_create_isNotPageOwner() {                       
     
+        expect(mockAuthentication.getAuthorities()).andReturn(grantedAuthoritiesList);
+        expect(mockAuthentication.getPrincipal()).andReturn(user2);
+        expect(mockPageRepository.get(VALID_PAGE_ID)).andReturn(page);
+        replay(mockAuthentication); 
+        replay(mockPageRepository);
+        assertThat(defaultPagePermissionEvaluator.hasPermission(mockAuthentication, page,
Permission.CREATE), is(false));        
+        verify(mockAuthentication);
+        verify(mockPageRepository);
+    }       
+    
+    @Test
     public void testHasPermission_3args_delete_isPageOwner() {                          
  
         expect(mockAuthentication.getAuthorities()).andReturn(grantedAuthoritiesList);
         expect(mockAuthentication.getPrincipal()).andReturn(user);
@@ -181,14 +199,30 @@ public class DefaultPagePermissionEvalua
     }    
     
     @Test
-    public void testHasPermission_4args_create() {                             
+    public void testHasPermission_4args_create_isPageOwner() {                          
  
         expect(mockAuthentication.getAuthorities()).andReturn(grantedAuthoritiesList);
+        expect(mockAuthentication.getPrincipal()).andReturn(user);
+        expect(mockPageRepository.get(VALID_PAGE_ID)).andReturn(page);
         replay(mockAuthentication);      
+        replay(mockPageRepository);     
         assertThat(defaultPagePermissionEvaluator.hasPermission(mockAuthentication, VALID_PAGE_ID,
Page.class.getName(), Permission.CREATE), is(true));        
         verify(mockAuthentication);
+        verify(mockPageRepository);
     }     
     
     @Test
+    public void testHasPermission_4args_create_isNotPageOwner() {                       
     
+        expect(mockAuthentication.getAuthorities()).andReturn(grantedAuthoritiesList);
+        expect(mockAuthentication.getPrincipal()).andReturn(user2);
+        expect(mockPageRepository.get(VALID_PAGE_ID)).andReturn(page);
+        replay(mockAuthentication);      
+        replay(mockPageRepository);     
+        assertThat(defaultPagePermissionEvaluator.hasPermission(mockAuthentication, VALID_PAGE_ID,
Page.class.getName(), Permission.CREATE), is(false));        
+        verify(mockAuthentication);
+        verify(mockPageRepository);
+    }         
+    
+    @Test
     public void testHasPermission_4args_delete_isPageOwner() {                          
  
         expect(mockAuthentication.getAuthorities()).andReturn(grantedAuthoritiesList);
         expect(mockAuthentication.getPrincipal()).andReturn(user);
@@ -259,4 +293,34 @@ public class DefaultPagePermissionEvalua
         verify(mockAuthentication);
         verify(mockPageRepository);
     }         
+    
+    @Test
+    public void testHasPermission_4args_update_isPageOwner_withRaveSecurityContextObject()
{                             
+        RaveSecurityContext raveSecurityContext = new RaveSecurityContext(VALID_USER_ID,
"org.apache.rave.portal.model.User");
+                
+        expect(mockAuthentication.getPrincipal()).andReturn(user);
+        replay(mockAuthentication);      
+        assertThat(defaultPagePermissionEvaluator.hasPermission(mockAuthentication, raveSecurityContext,
Page.class.getName(), Permission.UPDATE), is(true));        
+        verify(mockAuthentication);
+    } 
+    
+    @Test(expected=IllegalArgumentException.class)
+    public void testHasPermission_4args_update_isPageOwner_withInvalidRaveSecurityContextType()
{                             
+        RaveSecurityContext raveSecurityContext = new RaveSecurityContext(VALID_USER_ID,
"java.lang.String");
+                
+        expect(mockAuthentication.getPrincipal()).andReturn(user);
+        replay(mockAuthentication);      
+        defaultPagePermissionEvaluator.hasPermission(mockAuthentication, raveSecurityContext,
Page.class.getName(), Permission.UPDATE);        
+        verify(mockAuthentication);
+    }    
+    
+    @Test(expected=IllegalArgumentException.class)
+    public void testHasPermission_4args_update_isPageOwner_withUnknownRaveSecurityContextType()
{                             
+        RaveSecurityContext raveSecurityContext = new RaveSecurityContext(VALID_USER_ID,
"foo.bar.DummyClass");
+                
+        expect(mockAuthentication.getPrincipal()).andReturn(user);
+        replay(mockAuthentication);      
+        defaultPagePermissionEvaluator.hasPermission(mockAuthentication, raveSecurityContext,
Page.class.getName(), Permission.UPDATE);        
+        verify(mockAuthentication);
+    }    
 }
\ No newline at end of file

Added: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/AbstractRestApi.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/AbstractRestApi.java?rev=1185340&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/AbstractRestApi.java
(added)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/AbstractRestApi.java
Mon Oct 17 19:27:21 2011
@@ -0,0 +1,62 @@
+/*
+ * 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.web.api.rest;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.util.ClassUtils;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+/**
+ * Abstract class containing common functionality that should be shared across
+ * all Rest Api classes
+ *  
+ * @author carlucci
+ */
+public abstract class AbstractRestApi {
+    private Logger logger = LoggerFactory.getLogger(getClass());
+    
+     /**
+     * Return a 403 response code when any org.springframework.security.access.AccessDeniedException
+     * is thrown from any of the API methods due to security restrictions     
+     * 
+     * @param ex the AccessDeniedException
+     * @param request the http request
+     * @param response the http response
+     */
+    @ExceptionHandler(AccessDeniedException.class) 
+    public void handleAccessDeniedException(Exception ex, HttpServletRequest request, HttpServletResponse
response) {
+        logger.info("AccessDeniedException: " + request.getUserPrincipal().getName() + "
attempted to access resource " + request.getRequestURL(), ex);
+        response.setStatus(HttpStatus.FORBIDDEN.value());    
+    }
+    
+    // TODO RAVE-240 - when we implement security we can implement different exception
+    //        handlers for different errors (unauthorized, resource not found, etc)
+    @ExceptionHandler(Exception.class)
+    public String handleException(Exception ex, HttpServletRequest request, HttpServletResponse
response) {
+        // RAVE-240 lowered the log level to info
+        logger.info("Error occured while accessing " + request.getRequestURL(), ex);
+        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+        return ClassUtils.getShortName(ex.getClass());
+    }    
+}
\ No newline at end of file

Modified: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/PageApi.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/PageApi.java?rev=1185340&r1=1185339&r2=1185340&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/PageApi.java
(original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/PageApi.java
Mon Oct 17 19:27:21 2011
@@ -27,12 +27,9 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Controller;
-import org.springframework.util.ClassUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import org.springframework.security.access.AccessDeniedException;
 
 /**
  * Handler for all services exposed under the /api/rest/page path.
@@ -41,8 +38,8 @@ import org.springframework.security.acce
  */
 @Controller(value="restPageApi")
 @RequestMapping("/api/rest/page/*")
-public class PageApi {
-    private static Logger logger = LoggerFactory.getLogger(PageApi.class);
+public class PageApi extends AbstractRestApi {
+    private Logger logger = LoggerFactory.getLogger(getClass());
     private PageService pageService;
     
     @Autowired
@@ -62,6 +59,7 @@ public class PageApi {
     @ResponseBody
     @RequestMapping(value = "{pageId}", method = RequestMethod.GET)
     public Page getPage(@PathVariable long pageId, @RequestParam(required=false) boolean
export) {
+        logger.debug("GET received for /api/rest/page/" + pageId);        
         Page page = pageService.getPage(pageId);
         if(export) {
             modifyForExport(page);
@@ -69,33 +67,6 @@ public class PageApi {
         return page;
     }
 
-    /**
-     * Return a 403 response code when any org.springframework.security.access.AccessDeniedException
-     * is thrown from any of the API methods due to security restrictions
-     * 
-     * TODO: this should probably be moved up to an AbstractRestApi class since
-     * it seems common enough for all RestApi controllers
-     * 
-     * @param ex the AccessDeniedException
-     * @param request the http request
-     * @param response the http response
-     */
-    @ExceptionHandler(AccessDeniedException.class) 
-    public void handleAccessDeniedException(Exception ex, HttpServletRequest request, HttpServletResponse
response) {
-        logger.info("AccessDeniedException: " + request.getUserPrincipal().getName() + "
attempted to access resource " + request.getRequestURL(), ex);
-        response.setStatus(HttpStatus.FORBIDDEN.value());    
-    }
-    
-    // TODO RAVE-240 - when we implement security we can implement different exception
-    //        handlers for different errors (unauthorized, resource not found, etc)
-    @ExceptionHandler(Exception.class)
-    public String handleException(Exception ex, HttpServletRequest request, HttpServletResponse
response) {
-        // RAVE-240 lowered the log level to info
-        logger.info("Error occured while accessing " + request.getRequestURL(), ex);
-        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
-        return ClassUtils.getShortName(ex.getClass());
-    }
-
     private static void modifyForExport(Page page) {
         page.setOwner(null);
         for(Region r : page.getRegions()){

Modified: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/RegionWidgetApi.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/RegionWidgetApi.java?rev=1185340&r1=1185339&r2=1185340&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/RegionWidgetApi.java
(original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/RegionWidgetApi.java
Mon Oct 17 19:27:21 2011
@@ -37,8 +37,9 @@ import org.apache.rave.portal.model.Regi
  */
 @Controller
 @RequestMapping("/api/rest/regionWidgets")
-public class RegionWidgetApi {
+public class RegionWidgetApi extends AbstractRestApi {
     private static Logger logger = LoggerFactory.getLogger(RegionWidgetApi.class);
+    
 
     private RegionWidgetService regionWidgetService;
 

Modified: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/WidgetApi.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/WidgetApi.java?rev=1185340&r1=1185339&r2=1185340&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/WidgetApi.java
(original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rest/WidgetApi.java
Mon Oct 17 19:27:21 2011
@@ -30,7 +30,7 @@ import org.springframework.web.bind.anno
  */
 @Controller
 @RequestMapping("/api/rest/widgets")
-public class WidgetApi {
+public class WidgetApi extends AbstractRestApi {
     private static Logger logger = LoggerFactory.getLogger(WidgetApi.class);
 
     @RequestMapping(value = "/", method = RequestMethod.GET)

Added: incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rest/AbstractRestApiTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rest/AbstractRestApiTest.java?rev=1185340&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rest/AbstractRestApiTest.java
(added)
+++ incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rest/AbstractRestApiTest.java
Mon Oct 17 19:27:21 2011
@@ -0,0 +1,75 @@
+/*
+ * 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.web.api.rest;
+
+import java.security.Principal;
+import org.springframework.http.HttpStatus;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.util.ClassUtils;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.CoreMatchers.*;
+
+
+/**
+ *
+ * @author carlucci
+ */
+public class AbstractRestApiTest {
+    private AbstractRestApiImpl abstractRestApiImpl;
+    private MockHttpServletRequest request;
+    private MockHttpServletResponse response;
+       
+    
+    @Before
+    public void setUp() {
+        request = new MockHttpServletRequest();
+        response = new MockHttpServletResponse();
+        abstractRestApiImpl = new AbstractRestApiImpl();
+    }
+       
+    @Test
+    public void testHandleException() {
+        RuntimeException re = new RuntimeException("error");        
+        String value = abstractRestApiImpl.handleException(re, request, response);
+        
+        assertThat(value, is(ClassUtils.getShortName(re.getClass())));
+        assertThat(response.getStatus(), is(HttpStatus.INTERNAL_SERVER_ERROR.value())); 
 
+    }
+    
+    @Test
+    public void testHandleAccessDeniedException() {
+        Principal principal = createMock(Principal.class);                
+        request.setUserPrincipal(principal);
+        AccessDeniedException ade = new AccessDeniedException("error");        
+        
+        expect(principal.getName()).andReturn("theuser");
+        replay(principal);        
+        abstractRestApiImpl.handleAccessDeniedException(ade, request, response);        
+        assertThat(response.getStatus(), is(HttpStatus.FORBIDDEN.value()));   
+        verify(principal);
+    }    
+
+    class AbstractRestApiImpl extends AbstractRestApi { }
+}

Modified: incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rest/PageApiTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rest/PageApiTest.java?rev=1185340&r1=1185339&r2=1185340&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rest/PageApiTest.java
(original)
+++ incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rest/PageApiTest.java
Mon Oct 17 19:27:21 2011
@@ -42,14 +42,12 @@ import static org.hamcrest.CoreMatchers.
 public class PageApiTest {    
     private PageApi pageApi;    
     private PageService pageService;
-    private MockHttpServletRequest request;
     private MockHttpServletResponse response;
     
     private final long PAGE_ID = 1L;
     
     @Before
     public void setUp() {
-        request = new MockHttpServletRequest();
         response = new MockHttpServletResponse();
         pageService = createMock(PageService.class);
         pageApi = new PageApi(pageService);     
@@ -97,27 +95,5 @@ public class PageApiTest {    
         
         assertThat(response.getStatus(), is(HttpStatus.NO_CONTENT.value()));   
         verify(pageService);
-    }
-    
-    @Test
-    public void testHandleException() {
-        RuntimeException re = new RuntimeException("error");        
-        String value = pageApi.handleException(re, request, response);
-        
-        assertThat(value, is(ClassUtils.getShortName(re.getClass())));
-        assertThat(response.getStatus(), is(HttpStatus.INTERNAL_SERVER_ERROR.value())); 
 
-    }
-    
-    @Test
-    public void testHandleAccessDeniedException() {
-        Principal principal = createMock(Principal.class);                
-        request.setUserPrincipal(principal);
-        AccessDeniedException ade = new AccessDeniedException("error");        
-        
-        expect(principal.getName()).andReturn("theuser");
-        replay(principal);        
-        pageApi.handleAccessDeniedException(ade, request, response);        
-        assertThat(response.getStatus(), is(HttpStatus.FORBIDDEN.value()));   
-        verify(principal);
-    }    
+    }  
 }

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/applicationContext-security.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/applicationContext-security.xml?rev=1185340&r1=1185339&r2=1185340&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/applicationContext-security.xml
(original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/applicationContext-security.xml
Mon Oct 17 19:27:21 2011
@@ -65,7 +65,7 @@
     </security:global-method-security>
     
     <!-- override the default permissionEvaluator bean used by Spring Security with our
custom RavePermissionEvaluator -->
-    <bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
+    <bean id="expressionHandler" class="org.apache.rave.portal.security.impl.RaveMethodSecurityExpressionHandler">
         <property name="permissionEvaluator" ref="ravePermissionEvaluator" />     
      
     </bean>
 </beans>



Mime
View raw message