WICKET-5749 add AuthorizeResource to auth-roles so Resources can be protected too
Also cleaned up and expanded AnnotationsRoleAuthorizationStrategyTest. Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/b8b9b301 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/b8b9b301 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/b8b9b301 Branch: refs/heads/pr-86-media_tags Commit: b8b9b30173921215972238a34395725a08c70fb3 Parents: 05b32f5 Author: Carl-Eric Menzel <[email protected]> Authored: Mon Feb 23 15:39:48 2015 +0100 Committer: Carl-Eric Menzel <[email protected]> Committed: Mon Feb 23 15:56:36 2015 +0100 ---------------------------------------------------------------------- .../AnnotationsRoleAuthorizationStrategy.java | 20 ++ .../role/annotations/AuthorizeResource.java | 42 ++++ ...nnotationsRoleAuthorizationStrategyTest.java | 201 +++++++++++++++++-- 3 files changed, 241 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/b8b9b301/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AnnotationsRoleAuthorizationStrategy.java ---------------------------------------------------------------------- diff --git a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AnnotationsRoleAuthorizationStrategy.java b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AnnotationsRoleAuthorizationStrategy.java index 4aa4e92..077f096 100644 --- a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AnnotationsRoleAuthorizationStrategy.java +++ b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AnnotationsRoleAuthorizationStrategy.java @@ -22,6 +22,8 @@ import org.apache.wicket.authroles.authorization.strategies.role.AbstractRoleAut import org.apache.wicket.authroles.authorization.strategies.role.IRoleCheckingStrategy; import org.apache.wicket.authroles.authorization.strategies.role.Roles; import org.apache.wicket.request.component.IRequestableComponent; +import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.request.resource.IResource; /** @@ -140,4 +142,22 @@ public class AnnotationsRoleAuthorizationStrategy extends AbstractRoleAuthorizat } return true; } + + @Override + public boolean isResourceAuthorized(IResource resource, PageParameters pageParameters) + { + return checkResource(resource.getClass().getAnnotation(AuthorizeResource.class)) || checkResource( + resource.getClass().getPackage().getAnnotation(AuthorizeResource.class)); + } + + private boolean checkResource(AuthorizeResource annotation) + { + if (annotation != null) + { + return hasAny(new Roles(annotation.value())); + } else + { + return false; + } + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/b8b9b301/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AuthorizeResource.java ---------------------------------------------------------------------- diff --git a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AuthorizeResource.java b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AuthorizeResource.java new file mode 100644 index 0000000..a78eb37 --- /dev/null +++ b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AuthorizeResource.java @@ -0,0 +1,42 @@ +/* + * 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.wicket.authroles.authorization.strategies.role.annotations; + +import java.lang.annotation.*; + +/** + * Annotation for configuring what roles are allowed for requesting the annotated resource. It works analogously + * to {@link org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation}. + * + * @author Carl-Eric Menzel + * @see org.apache.wicket.authorization.IAuthorizationStrategy + * @see org.apache.wicket.authorization.strategies.role.annotations.AnnotationsRoleAuthorizationStrategy + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.PACKAGE, ElementType.TYPE}) +@Documented +@Inherited +public @interface AuthorizeResource +{ + + /** + * Gets the roles that are allowed to take the action. + * + * @return the roles that are allowed. Returns a zero length array by default + */ + String[] value() default {}; +} http://git-wip-us.apache.org/repos/asf/wicket/blob/b8b9b301/wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AnnotationsRoleAuthorizationStrategyTest.java ---------------------------------------------------------------------- diff --git a/wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AnnotationsRoleAuthorizationStrategyTest.java b/wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AnnotationsRoleAuthorizationStrategyTest.java index d0492cf..8371990 100644 --- a/wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AnnotationsRoleAuthorizationStrategyTest.java +++ b/wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authorization/strategies/role/annotations/AnnotationsRoleAuthorizationStrategyTest.java @@ -16,52 +16,209 @@ */ package org.apache.wicket.authroles.authorization.strategies.role.annotations; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import org.apache.wicket.Component; import org.apache.wicket.authroles.authorization.strategies.role.IRoleCheckingStrategy; import org.apache.wicket.authroles.authorization.strategies.role.Roles; import org.apache.wicket.markup.html.WebComponent; -import org.junit.Assert; +import org.apache.wicket.request.resource.IResource; import org.junit.Test; import org.mockito.Mockito; /** * Tests for {@link AnnotationsRoleAuthorizationStrategy} */ -public class AnnotationsRoleAuthorizationStrategyTest extends Assert +public class AnnotationsRoleAuthorizationStrategyTest { - /** - * https://issues.apache.org/jira/browse/WICKET-3974 - */ + @Test - public void allowNonDeniedRoles() + public void allowsRenderWithRequiredRoleAndNoDeniedRole() { AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( - new IRoleCheckingStrategy() - { - @Override - public boolean hasAnyRole(Roles roles) - { - return roles.contains("role1"); - } - }); - + roles("role1")); // use mock to not need Application in the thread - TestComponent component = Mockito.mock(TestComponent.class); + TestComponent_Render component = Mockito + .mock(TestComponent_Render.class); assertTrue(strategy.isActionAuthorized(component, Component.RENDER)); } - /** - * A component without denied roles. - */ - @AuthorizeAction(action = "RENDER", roles = { "role1" }) - private static class TestComponent extends WebComponent + @Test + public void deniesRenderWithoutRequiredRole() + { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role2")); + TestComponent_Render component = Mockito + .mock(TestComponent_Render.class); + assertFalse(strategy.isActionAuthorized(component, Component.RENDER)); + } + + @Test + public void deniesRenderWithRequiredRoleAndDeniedRole() + { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role1", "role3")); + TestComponent_Render component = Mockito + .mock(TestComponent_Render.class); + assertFalse(strategy.isActionAuthorized(component, Component.RENDER)); + } + + @Test + public void deniesRenderWithDeniedRole() + { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role3")); + TestComponent_Render component = Mockito + .mock(TestComponent_Render.class); + assertFalse(strategy.isActionAuthorized(component, Component.RENDER)); + } + + @Test + public void allowsEnableWithRequiredRole() { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role1")); + TestComponent_Enable component = Mockito + .mock(TestComponent_Enable.class); + assertTrue(strategy.isActionAuthorized(component, Component.ENABLE)); + } + + @Test + public void deniesEnableWithoutRequiredRoleAndNoDeniedRole() + { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role2")); + TestComponent_Enable component = Mockito + .mock(TestComponent_Enable.class); + assertFalse(strategy.isActionAuthorized(component, Component.ENABLE)); + } + + @Test + public void deniesEnableWithDeniedRole() + { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role3")); + TestComponent_Enable component = Mockito + .mock(TestComponent_Enable.class); + assertFalse(strategy.isActionAuthorized(component, Component.ENABLE)); + } + + @Test + public void deniesEnableWithRequiredRoleAndDeniedRole() + { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role1", "role3")); + TestComponent_Enable component = Mockito + .mock(TestComponent_Enable.class); + assertFalse(strategy.isActionAuthorized(component, Component.ENABLE)); + } + + @Test + public void allowsInstantiationWithRequiredRole() throws Exception + { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role1")); + assertTrue(strategy + .isInstantiationAuthorized(TestComponent_Instantiate.class)); + } + + @Test + public void deniesInstantiationWithoutRequiredRole() throws Exception + { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role2")); + assertFalse(strategy + .isInstantiationAuthorized(TestComponent_Instantiate.class)); + } + + @Test + public void allowsResourceWithRequiredRole() throws Exception + { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role1")); + IResource resource = Mockito.mock(TestResource.class); + assertTrue(strategy.isResourceAuthorized(resource, null)); + } + + @Test + public void deniesResourceWithoutRequiredRole() throws Exception + { + AnnotationsRoleAuthorizationStrategy strategy = new AnnotationsRoleAuthorizationStrategy( + roles("role2")); + IResource resource = Mockito.mock(TestResource.class); + assertFalse(strategy.isResourceAuthorized(resource, null)); + } + + @AuthorizeInstantiation({"role1"}) + private static class TestComponent_Instantiate extends WebComponent + { + private static final long serialVersionUID = 1L; - private TestComponent() + private TestComponent_Instantiate() { super("notUsed"); } } + + @AuthorizeAction(action = "RENDER", roles = {"role1"}, deny = {"role3"}) + private static class TestComponent_Render extends WebComponent + { + + private static final long serialVersionUID = 1L; + + private TestComponent_Render() + { + super("notUsed"); + } + + } + + @AuthorizeAction(action = "ENABLE", roles = {"role1"}, deny = {"role3"}) + private static class TestComponent_Enable extends WebComponent + { + private static final long serialVersionUID = 1L; + + private TestComponent_Enable() + { + super("notUsed"); + } + + } + + @AuthorizeResource("role1") + private static class TestResource implements IResource + { + /** + * Renders this resource to response using the provided attributes. + * + * @param attributes + */ + @Override + public void respond(Attributes attributes) + { + ; // NOOP + } + } + + /** + * Create a test role checking strategy that is simply given a list of roles + * and returns true if that list contains any of the asked-for roles. + * + * @param availableRoles rules that this role checker should have + * @return test role checking strategy + */ + private IRoleCheckingStrategy roles(final String... availableRoles) + { + return new IRoleCheckingStrategy() + { + @Override + public boolean hasAnyRole(Roles requiredRoles) + { + return requiredRoles.hasAnyRole(new Roles(availableRoles)); + } + }; + } }
