/** * Copyright (C) 2011 JTalks.org Team * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package org.jtalks.jcommune.service.security; import org.jtalks.common.model.dao.GroupDao; import org.jtalks.common.model.entity.Group; import org.jtalks.common.model.entity.User; import org.jtalks.common.model.permissions.BranchPermission; import org.jtalks.common.model.permissions.JtalksPermission; import org.jtalks.common.model.permissions.ProfilePermission; import org.jtalks.jcommune.model.entity.JCUser; import org.jtalks.jcommune.model.entity.UserInfo; import org.jtalks.jcommune.plugin.api.PluginPermissionManager; import org.jtalks.jcommune.plugin.api.exceptions.NotFoundException; import org.jtalks.jcommune.service.security.acl.*; import org.jtalks.jcommune.service.security.acl.sids.JtalksSidFactory; import org.jtalks.jcommune.service.security.acl.sids.UserGroupSid; import org.jtalks.jcommune.service.security.acl.sids.UserSid; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.springframework.security.acls.domain.ObjectIdentityImpl; import org.springframework.security.acls.jdbc.JdbcMutableAclService; import org.springframework.security.acls.model.AccessControlEntry; import org.springframework.security.acls.model.MutableAcl; import org.springframework.security.acls.model.ObjectIdentity; import org.springframework.security.acls.model.Sid; import org.springframework.security.core.Authentication; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static org.mockito.Matchers.any; import static org.mockito.Mockito.when; /** * @author stanislav bashkirtsev */ public class AclGroupPermissionEvaluatorTest { @Mock private AclManager aclManager; @Mock private AclUtil aclUtil; @Mock private GroupDao groupDao; @Mock private JtalksSidFactory sidFactory; @Mock private ExtendedMutableAcl mutableAcl; @Mock private Authentication authentication; @Mock private JdbcMutableAclService mutableAclService; @Mock private MutableAcl acl; @Mock private PluginPermissionManager pluginManager; @Mock private SecurityService securityService; private JCUser user; private AclGroupPermissionEvaluator evaluator; private UserGroupSid groupSid; private UserSid userSid; private ObjectIdentityImpl objectIdentity; private long targetId = 1L; private String targetType = "BRANCH"; private String permission = "BranchPermission.CREATE_POSTS"; private BranchPermission generalPermission = BranchPermission.CREATE_POSTS; private BranchPermission someOtherPermission = BranchPermission.CLOSE_TOPICS; @BeforeMethod public void init() throws NotFoundException { MockitoAnnotations.initMocks(this); evaluator = new AclGroupPermissionEvaluator(aclManager, aclUtil, sidFactory, mutableAclService, pluginManager, securityService); objectIdentity = new ObjectIdentityImpl(targetType, targetId); Mockito.when(aclUtil.createIdentity(targetId, targetType)).thenReturn(objectIdentity); user = new JCUser("username", "email@jtalks.org", "password"); user.setId(1); userSid = new UserSid(user.getId()); groupSid = new UserGroupSid(targetId); Group group = new Group(); group.setId(2); group.setUsers(Collections.<User>singletonList(user)); user.setGroups(Collections.singletonList(group)); when(sidFactory.createPrincipal(authentication)).thenReturn(userSid); when(sidFactory.create(group)).thenReturn(groupSid); when(authentication.getPrincipal()).thenReturn(new UserInfo(user)); when(mutableAclService.readAclById(Mockito.any(ObjectIdentity.class))).thenReturn(acl); when(securityService.getFullUserInfoFrom(any(Authentication.class))).thenReturn(user); List<GroupAce> controlEntries = new ArrayList<>(); Mockito.when(aclManager.getGroupPermissionsFilteredByPermissionOn(Mockito.any(ObjectIdentity.class), Mockito.any(JtalksPermission.class))).thenReturn(controlEntries); } @Test public void testHasPermissionForUserSidSuccessTest() throws Exception { List<AccessControlEntry> aces = new ArrayList<>(); aces.add(createAccessControlEntry(generalPermission, true, userSid)); aces.add(createAccessControlEntry(ProfilePermission.EDIT_OWN_PROFILE, true, userSid)); aces.add(createAccessControlEntry(BranchPermission.CLOSE_TOPICS, true, userSid)); Mockito.when(acl.getEntries()).thenReturn(aces); Mockito.when(aclUtil.getAclFor(objectIdentity)).thenReturn(mutableAcl); Mockito.when(mutableAcl.getEntries()).thenReturn(aces); String targetIdString = "1"; Assert.assertTrue(evaluator.hasPermission(authentication, targetIdString, targetType, permission)); Assert.assertTrue(evaluator.hasPermission(authentication, targetId, targetType, permission)); Assert.assertTrue(evaluator.hasPermission(authentication, targetId, targetType, "ProfilePermission.EDIT_OWN_PROFILE")); Assert.assertTrue(evaluator.hasPermission(authentication, targetId, targetType, "BranchPermission.CLOSE_TOPICS")); Assert.assertFalse(evaluator.hasPermission(authentication, targetId, targetType, "GeneralPermission.READ")); } @Test public void testHasPermissionForPermissionOnGroupSuccessTest() throws Exception { setEnvForPermissionOnGroupTests(true); Assert.assertTrue(evaluator.hasPermission(authentication, targetId, targetType, permission)); Assert.assertFalse(evaluator.hasPermission(authentication, targetId, targetType, "GeneralPermission.READ")); } @Test public void testHasPermissionForPermissionOnGroupNonExistentUserTest() throws Exception { setEnvForPermissionOnGroupTests(true); long nonExistentId = -1L; user.setId(nonExistentId); user.setGroups(Collections.<Group>emptyList()); when(securityService.getFullUserInfoFrom(any(Authentication.class))).thenReturn(user); Assert.assertFalse(evaluator.hasPermission(authentication, nonExistentId, targetType, permission)); Assert.assertFalse(evaluator.hasPermission(authentication, nonExistentId, targetType, "GeneralPermission.READ")); } @Test public void testHasPermissionForPermissionOnGroupNotSuccessTest() throws Exception { setEnvForPermissionOnGroupTests(false); Assert.assertFalse(evaluator.hasPermission(authentication, targetId, targetType, permission)); } private void setEnvForPermissionOnGroupTests(boolean isGranted) { ObjectIdentity groupIdentity = new ObjectIdentityImpl("GROUP", targetId); Mockito.when(aclUtil.createIdentity(targetId, "GROUP")).thenReturn(groupIdentity); List<AccessControlEntry> aces = new ArrayList<>(); aces.add(createAccessControlEntry(generalPermission, isGranted, groupSid)); Mockito.when(acl.getEntries()).thenReturn(aces); Mockito.when(mutableAcl.getEntries()).thenReturn(aces); Mockito.when(aclUtil.getAclFor(objectIdentity)).thenReturn(mutableAcl); Mockito.when(aclUtil.getAclFor(groupIdentity)).thenReturn(mutableAcl); List<GroupAce> controlEntries = new ArrayList<>(); controlEntries.add(createGroupAce(generalPermission, isGranted)); Mockito.when(aclManager.getGroupPermissionsFilteredByPermissionOn(Mockito.any(ObjectIdentity.class), Mockito.any(JtalksPermission.class))).thenReturn(controlEntries); } @Test public void testHasPermissionForGroupSidSuccessTest() throws Exception { setEnvForGroupSidTests(true); Assert.assertTrue(evaluator.hasPermission(authentication, targetId, targetType, permission)); } @Test public void testHasPermissionForGroupSidNotSuccessTest() throws Exception { setEnvForGroupSidTests(false); Assert.assertFalse(evaluator.hasPermission(authentication, targetId, targetType, permission)); } private void setEnvForGroupSidTests(boolean isGranted) { List<AccessControlEntry> aces = new ArrayList<>(); Mockito.when(aclUtil.getAclFor(objectIdentity)).thenReturn(mutableAcl); Mockito.when(mutableAcl.getEntries()).thenReturn(aces); Mockito.when(acl.getEntries()).thenReturn(aces); List<GroupAce> controlEntries = new ArrayList<>(); controlEntries.add(createGroupAce(someOtherPermission, true)); controlEntries.add(createGroupAce(someOtherPermission, false)); controlEntries.add(createGroupAce(generalPermission, isGranted)); Mockito.when(aclManager.getGroupPermissionsFilteredByPermissionOn(Mockito.any(ObjectIdentity.class), Mockito.any(JtalksPermission.class))).thenReturn(controlEntries); } @Test public void testHasPermissionForUserSidNotSuccessTest() throws Exception { List<AccessControlEntry> aces = new ArrayList<>(); aces.add(createAccessControlEntry(generalPermission, false, userSid)); Mockito.when(aclUtil.getAclFor(objectIdentity)).thenReturn(mutableAcl); Mockito.when(mutableAcl.getEntries()).thenReturn(aces); Mockito.when(acl.getEntries()).thenReturn(aces); Assert.assertFalse(evaluator.hasPermission(authentication, targetId, targetType, permission)); } @Test public void testHasPermissionForUserSidEmptyTest() throws Exception { List<AccessControlEntry> aces = new ArrayList<>(); Mockito.when(aclUtil.getAclFor(objectIdentity)).thenReturn(mutableAcl); Mockito.when(mutableAcl.getEntries()).thenReturn(aces); Mockito.when(acl.getEntries()).thenReturn(aces); Assert.assertFalse(evaluator.hasPermission(authentication, targetId, targetType, permission)); } @Test(expectedExceptions = IllegalArgumentException.class) public void testHasPermissionForInvalidPermissionTest() throws Exception { List<AccessControlEntry> aces = new ArrayList<>(); Mockito.when(aclUtil.getAclFor(objectIdentity)).thenReturn(mutableAcl); Mockito.when(mutableAcl.getEntries()).thenReturn(aces); Mockito.when(acl.getEntries()).thenReturn(aces); Assert.assertFalse(evaluator.hasPermission(authentication, targetId, targetType, "123")); } @SuppressWarnings("deprecation") @Test(expectedExceptions = UnsupportedOperationException.class) public void testHasPermission() throws Exception { evaluator.hasPermission(authentication, targetId, permission); } private AccessControlEntry createAccessControlEntry(JtalksPermission permission, boolean isGranted, Sid sid) { AccessControlEntry accessControlEntry = Mockito.mock(AccessControlEntry.class); Mockito.when(accessControlEntry.getSid()).thenReturn(sid); Mockito.when(accessControlEntry.isGranting()).thenReturn(isGranted); Mockito.when(accessControlEntry.getPermission()).thenReturn(permission); return accessControlEntry; } private GroupAce createGroupAce(BranchPermission permission, boolean isGranted) { GroupAce groupAce = Mockito.mock(GroupAce.class); Group group = Mockito.mock(Group.class); List<User> users = new ArrayList<>(); users.add(user); Mockito.when(group.getUsers()).thenReturn(users); Mockito.when(groupAce.getGroup(groupDao)).thenReturn(group); Mockito.when(groupAce.getGroupId()).thenReturn(2L); Mockito.when(groupAce.isGranting()).thenReturn(isGranted); Mockito.when(groupAce.getPermission()).thenReturn(permission); return groupAce; } }