package org.molgenis.auth; import org.mockito.ArgumentCaptor; import org.mockito.Matchers; import org.molgenis.data.DataService; import org.molgenis.data.Entity; import org.molgenis.data.Repository; import org.molgenis.data.support.QueryImpl; import org.springframework.security.crypto.password.PasswordEncoder; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.List; import java.util.stream.Stream; import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; import static org.mockito.Mockito.*; import static org.molgenis.auth.GroupMemberMetaData.GROUP_MEMBER; import static org.molgenis.auth.UserAuthorityMetaData.USER_AUTHORITY; public class UserRepositoryDecoratorTest { private Repository<User> decoratedRepository; private Repository<UserAuthority> userAuthorityRepository; private Repository<GroupMember> groupMemberRepository; private UserRepositoryDecorator userRepositoryDecorator; private PasswordEncoder passwordEncoder; private DataService dataService; @SuppressWarnings("unchecked") @BeforeMethod public void setUp() { decoratedRepository = mock(Repository.class); userAuthorityRepository = mock(Repository.class); groupMemberRepository = mock(Repository.class); UserAuthorityFactory userAuthorityFactory = mock(UserAuthorityFactory.class); when(userAuthorityFactory.create()).thenAnswer(invocation -> mock(UserAuthority.class)); dataService = mock(DataService.class); when(dataService.getRepository(USER_AUTHORITY, UserAuthority.class)).thenReturn(userAuthorityRepository); when(dataService.getRepository(GROUP_MEMBER, GroupMember.class)).thenReturn(groupMemberRepository); passwordEncoder = mock(PasswordEncoder.class); userRepositoryDecorator = new UserRepositoryDecorator(decoratedRepository, userAuthorityFactory, dataService, passwordEncoder); } @Test public void testDelegate() throws Exception { Assert.assertEquals(userRepositoryDecorator.delegate(), decoratedRepository); } @Test public void addEntity() { String password = "password"; User user = mock(User.class); when(user.getPassword()).thenReturn(password); when(user.isSuperuser()).thenReturn(false); userRepositoryDecorator.add(user); verify(passwordEncoder).encode(password); verify(decoratedRepository).add(user); verify(userAuthorityRepository, times(0)).add(Matchers.any(UserAuthority.class)); } @SuppressWarnings("unchecked") @Test public void addStream() { String password = "password"; User user0 = mock(User.class); when(user0.getPassword()).thenReturn(password); when(user0.isSuperuser()).thenReturn(false); User user1 = mock(User.class); when(user1.getPassword()).thenReturn(password); when(user1.isSuperuser()).thenReturn(false); when(decoratedRepository.add(Matchers.any(Stream.class))).thenAnswer(invocation -> { Stream<Entity> entities = (Stream<Entity>) invocation.getArguments()[0]; List<Entity> entitiesList = entities.collect(toList()); return entitiesList.size(); }); Assert.assertEquals(userRepositoryDecorator.add(Stream.of(user0, user1)), Integer.valueOf(2)); verify(passwordEncoder, times(2)).encode(password); verify(userAuthorityRepository, times(0)).add(Matchers.any(UserAuthority.class)); } @Test public void delete() { User user = mock(User.class); Stream<GroupMember> groupMembers = Stream.of(mock(GroupMember.class)); Stream<UserAuthority> userAuthorities = Stream.of(mock(UserAuthority.class)); when(dataService.findAll(USER_AUTHORITY, new QueryImpl<UserAuthority>().eq(UserAuthorityMetaData.USER, user), UserAuthority.class)).thenReturn(userAuthorities); when(dataService.findAll(GROUP_MEMBER, new QueryImpl<GroupMember>().eq(GroupMemberMetaData.USER, user), GroupMember.class)).thenReturn(groupMembers); userRepositoryDecorator.delete(user); verify(decoratedRepository, times(1)).delete(user); verify(dataService, times(1)).delete(USER_AUTHORITY, userAuthorities); verify(dataService, times(1)).delete(GROUP_MEMBER, groupMembers); } @SuppressWarnings("unchecked") @Test public void deleteStream() { User user = mock(User.class); Stream<User> entities = Stream.of(user); Stream<GroupMember> groupMembers = Stream.of(mock(GroupMember.class)); Stream<UserAuthority> userAuthorities = Stream.of(mock(UserAuthority.class)); when(dataService.findAll(USER_AUTHORITY, new QueryImpl<UserAuthority>().eq(UserAuthorityMetaData.USER, user), UserAuthority.class)).thenReturn(userAuthorities); when(dataService.findAll(GROUP_MEMBER, new QueryImpl<GroupMember>().eq(GroupMemberMetaData.USER, user), GroupMember.class)).thenReturn(groupMembers); ArgumentCaptor<Stream> captor = ArgumentCaptor.forClass(Stream.class); userRepositoryDecorator.delete(entities); verify(decoratedRepository, times(1)).delete(captor.capture()); captor.getValue().forEach(u -> { }); verify(dataService, times(1)).delete(USER_AUTHORITY, userAuthorities); verify(dataService, times(1)).delete(GROUP_MEMBER, groupMembers); } @Test public void deleteById() { User user = mock(User.class); when(userRepositoryDecorator.findOneById("1")).thenReturn(user); Stream<GroupMember> groupMembers = Stream.of(mock(GroupMember.class)); Stream<UserAuthority> userAuthorities = Stream.of(mock(UserAuthority.class)); when(dataService.findAll(USER_AUTHORITY, new QueryImpl<UserAuthority>().eq(UserAuthorityMetaData.USER, user), UserAuthority.class)).thenReturn(userAuthorities); when(dataService.findAll(GROUP_MEMBER, new QueryImpl<GroupMember>().eq(GroupMemberMetaData.USER, user), GroupMember.class)).thenReturn(groupMembers); userRepositoryDecorator.delete(user); verify(decoratedRepository, times(1)).delete(user); verify(dataService, times(1)).delete(USER_AUTHORITY, userAuthorities); verify(dataService, times(1)).delete(GROUP_MEMBER, groupMembers); } @SuppressWarnings("unchecked") @Test public void deleteAllStream() { User user = mock(User.class); when(userRepositoryDecorator.findOneById("1")).thenReturn(user); Stream<GroupMember> groupMembers = Stream.of(mock(GroupMember.class)); Stream<UserAuthority> userAuthorities = Stream.of(mock(UserAuthority.class)); when(dataService.findAll(USER_AUTHORITY, new QueryImpl<UserAuthority>().eq(UserAuthorityMetaData.USER, user), UserAuthority.class)).thenReturn(userAuthorities); when(dataService.findAll(GROUP_MEMBER, new QueryImpl<GroupMember>().eq(GroupMemberMetaData.USER, user), GroupMember.class)).thenReturn(groupMembers); ArgumentCaptor<Stream> captor = ArgumentCaptor.forClass(Stream.class); userRepositoryDecorator.deleteAll(Stream.of("1")); verify(decoratedRepository, times(1)).deleteAll(captor.capture()); captor.getValue().forEach(u -> { }); verify(dataService, times(1)).delete(USER_AUTHORITY, userAuthorities); verify(dataService, times(1)).delete(GROUP_MEMBER, groupMembers); } @Test(expectedExceptions = UnsupportedOperationException.class) public void deleteAll() { userRepositoryDecorator.deleteAll(); } @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void updateStream() { when(passwordEncoder.encode("password")).thenReturn("passwordHash"); User currentUser = mock(User.class); when(currentUser.getId()).thenReturn("1"); when(currentUser.getPassword()).thenReturn("currentPasswordHash"); when(userRepositoryDecorator.findOneById("1")).thenReturn(currentUser); User user = mock(User.class); when(user.getId()).thenReturn("1"); when(user.getPassword()).thenReturn("password"); Stream<User> entities = Stream.of(user); ArgumentCaptor<Stream<User>> captor = ArgumentCaptor.forClass((Class) Stream.class); doNothing().when(decoratedRepository).update(captor.capture()); userRepositoryDecorator.update(entities); Assert.assertEquals(captor.getValue().collect(toList()), singletonList(user)); verify(user).setPassword("passwordHash"); // TODO add authority tests } @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void updateStreamUnchangedPassword() { when(passwordEncoder.encode("currentPasswordHash")).thenReturn("blaat"); User currentUser = mock(User.class); when(currentUser.getId()).thenReturn("1"); when(currentUser.getPassword()).thenReturn("currentPasswordHash"); when(userRepositoryDecorator.findOneById("1")).thenReturn(currentUser); User user = mock(User.class); when(user.getId()).thenReturn("1"); when(user.getPassword()).thenReturn("currentPasswordHash"); Stream<User> entities = Stream.of(user); ArgumentCaptor<Stream<User>> captor = ArgumentCaptor.forClass((Class) Stream.class); doNothing().when(decoratedRepository).update(captor.capture()); userRepositoryDecorator.update(entities); Assert.assertEquals(captor.getValue().collect(toList()), singletonList(user)); verify(user).setPassword("currentPasswordHash"); // TODO add authority tests } @Test public void addEntitySu() { String password = "password"; User user = mock(User.class); when(user.getId()).thenReturn("1"); when(user.getPassword()).thenReturn(password); when(user.isSuperuser()).thenReturn(true); when(decoratedRepository.findOneById("1")).thenReturn(user); userRepositoryDecorator.add(user); verify(passwordEncoder).encode(password); verify(decoratedRepository).add(user); } }