/* documentr - Edit, maintain, and present software documentation on the web. Copyright (C) 2012-2013 Maik Schreiber This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.blizzy.documentr.access; import static org.junit.Assert.*; import static org.mockito.Mockito.*; import java.io.IOException; import java.util.EnumSet; import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import de.blizzy.documentr.AbstractDocumentrTest; import de.blizzy.documentr.DocumentrConstants; import de.blizzy.documentr.access.GrantedAuthorityTarget.Type; import de.blizzy.documentr.page.IPageStore; import de.blizzy.documentr.page.Page; @RunWith(PowerMockRunner.class) @PrepareForTest(LoginNameUserDetailsService.class) public class DocumentrPermissionEvaluatorTest extends AbstractDocumentrTest { private static final String USER = "user"; //$NON-NLS-1$ @Mock private IPageStore pageStore; @Mock private UserStore userStore; @Mock private UserDetails userDetails; @InjectMocks private DocumentrPermissionEvaluator permissionEvaluator; private LoginNameUserDetailsService userDetailsService; @Before public void setUp() { userDetailsService = PowerMockito.mock(LoginNameUserDetailsService.class); Whitebox.setInternalState(permissionEvaluator, LoginNameUserDetailsService.class, userDetailsService); } @Test public void hasApplicationPermission() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( GrantedAuthorityTarget.APPLICATION, Permission.EDIT_PAGE)); assertTrue(permissionEvaluator.hasApplicationPermission( authentication, Permission.EDIT_PAGE)); } @Test public void hasApplicationPermissionMustHonorAdminPermission() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( GrantedAuthorityTarget.APPLICATION, Permission.ADMIN)); assertTrue(permissionEvaluator.hasApplicationPermission( authentication, Permission.EDIT_PAGE)); } @Test public void hasProjectPermission() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project", Type.PROJECT), Permission.EDIT_PAGE)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasProjectPermission( authentication, "project", Permission.EDIT_PAGE)); //$NON-NLS-1$ } @Test public void hasProjectPermissionMustCheckApplication() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( GrantedAuthorityTarget.APPLICATION, Permission.EDIT_PAGE)); assertTrue(permissionEvaluator.hasProjectPermission( authentication, "project", Permission.EDIT_PAGE)); //$NON-NLS-1$ } @Test public void hasProjectPermissionMustHonorAdminPermission() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project", Type.PROJECT), Permission.ADMIN)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasProjectPermission( authentication, "project", Permission.EDIT_PAGE)); //$NON-NLS-1$ } @Test public void hasAnyProjectPermission() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project", Type.PROJECT), Permission.EDIT_PAGE)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasAnyProjectPermission( authentication, Permission.EDIT_PAGE)); } @Test public void hasAnyProjectPermissionMustCheckApplication() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( GrantedAuthorityTarget.APPLICATION, Permission.EDIT_PAGE)); assertTrue(permissionEvaluator.hasAnyProjectPermission( authentication, Permission.EDIT_PAGE)); } @Test public void hasAnyProjectPermissionMustHonorAdminPermission() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project", Type.PROJECT), Permission.ADMIN)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasAnyProjectPermission( authentication, Permission.EDIT_PAGE)); } @Test public void hasBranchPermission() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project/branch", Type.BRANCH), Permission.EDIT_PAGE)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasBranchPermission( authentication, "project", "branch", Permission.EDIT_PAGE)); //$NON-NLS-1$ //$NON-NLS-2$ } @Test public void hasBranchPermissionMustCheckProject() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project", Type.PROJECT), Permission.EDIT_PAGE)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasBranchPermission( authentication, "project", "branch", Permission.EDIT_PAGE)); //$NON-NLS-1$ //$NON-NLS-2$ } @Test public void hasBranchPermissionMustHonorAdminPermission() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project/branch", Type.BRANCH), Permission.ADMIN)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasBranchPermission( authentication, "project", "branch", Permission.EDIT_PAGE)); //$NON-NLS-1$ //$NON-NLS-2$ } @Test public void hasAnyBranchPermission() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project/branch", Type.BRANCH), Permission.EDIT_PAGE)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasAnyBranchPermission( authentication, "project", Permission.EDIT_PAGE)); //$NON-NLS-1$ } @Test public void hasAnyBranchPermissionMustCheckProject() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project", Type.PROJECT), Permission.EDIT_PAGE)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasAnyBranchPermission( authentication, "project", Permission.EDIT_PAGE)); //$NON-NLS-1$ } @Test public void hasAnyBranchPermissionMustHonorAdminPermission() { Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project/branch", Type.BRANCH), Permission.ADMIN)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasAnyBranchPermission( authentication, "project", Permission.EDIT_PAGE)); //$NON-NLS-1$ } @Test public void hasPagePermissionMustCheckBranch() throws IOException { when(pageStore.getPage("project", "branch", DocumentrConstants.HOME_PAGE_NAME + "/foo", false)) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ .thenReturn(Page.fromText("title", "text")); //$NON-NLS-1$ //$NON-NLS-2$ Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( new GrantedAuthorityTarget("project/branch", Type.BRANCH), Permission.EDIT_PAGE)); //$NON-NLS-1$ assertTrue(permissionEvaluator.hasPagePermission(authentication, "project", "branch", DocumentrConstants.HOME_PAGE_NAME + "/foo", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ Permission.EDIT_PAGE)); } @Test public void hasPagePermissionWithPageRestrictingAccess() throws IOException { Page page = Page.fromText("title", "text"); //$NON-NLS-1$ //$NON-NLS-2$ page.setViewRestrictionRole("viewRole"); //$NON-NLS-1$ when(pageStore.getPage("project", "branch", DocumentrConstants.HOME_PAGE_NAME + "/foo", false)) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ .thenReturn(page); when(userStore.getUserAuthorities(USER)).thenReturn(Lists.newArrayList( new RoleGrantedAuthority(GrantedAuthorityTarget.APPLICATION, "viewRole"))); //$NON-NLS-1$ Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( GrantedAuthorityTarget.APPLICATION, Permission.VIEW)); assertTrue(permissionEvaluator.hasPagePermission(authentication, "project", "branch", DocumentrConstants.HOME_PAGE_NAME + "/foo", Permission.VIEW)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } @Test public void hasPagePermissionWithPageRestrictingAccessMustHonorAdminPermission() throws IOException { Page page = Page.fromText("title", "text"); //$NON-NLS-1$ //$NON-NLS-2$ page.setViewRestrictionRole("viewRole"); //$NON-NLS-1$ when(pageStore.getPage("project", "branch", DocumentrConstants.HOME_PAGE_NAME + "/foo", false)) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ .thenReturn(page); Authentication authentication = mockAuthentication(new PermissionGrantedAuthority( GrantedAuthorityTarget.APPLICATION, Permission.ADMIN)); assertTrue(permissionEvaluator.hasPagePermission(authentication, "project", "branch", DocumentrConstants.HOME_PAGE_NAME + "/foo", Permission.VIEW)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } @Test public void isAdmin() { when(userDetailsService.loadUserByUsername(USER)).thenReturn(userDetails); GrantedAuthority authority = new PermissionGrantedAuthority(GrantedAuthorityTarget.APPLICATION, Permission.ADMIN); doReturn(Sets.newHashSet(authority)).when(userDetails).getAuthorities(); assertTrue(permissionEvaluator.isAdmin(USER)); GrantedAuthorityTarget target = new GrantedAuthorityTarget("project", GrantedAuthorityTarget.Type.PROJECT); //$NON-NLS-1$ authority = new PermissionGrantedAuthority(target, Permission.ADMIN); doReturn(Sets.newHashSet(authority)).when(userDetails).getAuthorities(); assertFalse(permissionEvaluator.isAdmin(USER)); target = new GrantedAuthorityTarget("project", GrantedAuthorityTarget.Type.PROJECT); //$NON-NLS-1$ authority = new PermissionGrantedAuthority(target, Permission.VIEW); doReturn(Sets.newHashSet(authority)).when(userDetails).getAuthorities(); assertFalse(permissionEvaluator.isAdmin(USER)); } @Test public void isLastAdminRole() throws IOException { when(userStore.listUsers()).thenReturn(Lists.newArrayList(USER)); List<RoleGrantedAuthority> authorities = Lists.newArrayList(); when(userStore.getUserAuthorities(USER)).thenReturn(authorities); List<String> roleNames = Lists.newArrayList(); when(userStore.listRoles()).thenReturn(roleNames); roleNames.add("viewer"); //$NON-NLS-1$ RoleGrantedAuthority rga = new RoleGrantedAuthority(GrantedAuthorityTarget.APPLICATION, "viewer"); //$NON-NLS-1$ authorities.add(rga); Role role = mock(Role.class); when(role.getPermissions()).thenReturn(EnumSet.of(Permission.VIEW)); when(userStore.getRole("viewer")).thenReturn(role); //$NON-NLS-1$ assertFalse(permissionEvaluator.isLastAdminRole("viewer")); //$NON-NLS-1$ roleNames.add("admin"); //$NON-NLS-1$ rga = new RoleGrantedAuthority(GrantedAuthorityTarget.APPLICATION, "admin"); //$NON-NLS-1$ authorities.add(rga); role = mock(Role.class); when(role.getPermissions()).thenReturn(EnumSet.of(Permission.ADMIN)); when(userStore.getRole("admin")).thenReturn(role); //$NON-NLS-1$ assertTrue(permissionEvaluator.isLastAdminRole("admin")); //$NON-NLS-1$ roleNames.add("projectAdmin"); //$NON-NLS-1$ GrantedAuthorityTarget target = new GrantedAuthorityTarget("project", GrantedAuthorityTarget.Type.PROJECT); //$NON-NLS-1$ rga = new RoleGrantedAuthority(target, "projectAdmin"); //$NON-NLS-1$ authorities.add(rga); role = mock(Role.class); when(role.getPermissions()).thenReturn(EnumSet.of(Permission.ADMIN)); when(userStore.getRole("projectAdmin")).thenReturn(role); //$NON-NLS-1$ assertFalse(permissionEvaluator.isLastAdminRole("projectAdmin")); //$NON-NLS-1$ roleNames.add("admin2"); //$NON-NLS-1$ rga = new RoleGrantedAuthority(GrantedAuthorityTarget.APPLICATION, "admin2"); //$NON-NLS-1$ authorities.add(rga); role = mock(Role.class); when(role.getPermissions()).thenReturn(EnumSet.of(Permission.ADMIN)); when(userStore.getRole("admin2")).thenReturn(role); //$NON-NLS-1$ assertFalse(permissionEvaluator.isLastAdminRole("admin2")); //$NON-NLS-1$ } private Authentication mockAuthentication(GrantedAuthority... authorities) { return new AbstractAuthenticationToken(Sets.newHashSet(authorities)) { @Override public Object getPrincipal() { return USER; } @Override public Object getCredentials() { return null; } }; } }