package de.fd.fh.server.access; import com.mongodb.WriteResult; import de.fd.fh.server.user.UserId; import de.fd.fh.shared.network.messages.LoginRequest; import de.fd.fh.shared.network.messages.RegistrateRequest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import spark.HaltException; import java.time.LocalDateTime; import java.util.Base64; import java.util.Observable; import java.util.Observer; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.*; class AccessServiceTest implements Observer { private Object event; @BeforeEach void before() { this.event = null; } @Test void given_authenticatedUser_when_serverAuthenticateUser_should_authenticateUser() { final Access access = new Access( "testId", "testName", "testPwd", UserId.of("12345"), new AccessToken( "testToken", LocalDateTime.now(), Role.USER, UserId.of("12345") ), Role.USER); final AccessRepository repository = mock(AccessRepository.class); when(repository.findByToken(any())) .thenReturn(access); final String path = "/test/path"; final String token = "testToken"; final AccessToken result = new AccessService(repository).before(path, token); assertThat("User is not authenticated", result, notNullValue()); then(repository).should().findByToken(any()); then(repository).shouldHaveNoMoreInteractions(); } @Test void given_notAuthenticatedUser_when_serverAuthenticateUser_should_denyUser() { final Access access = new Access( "testId", "testName", "testPwd", UserId.of("12345"), null, Role.USER); final AccessRepository repository = mock(AccessRepository.class); when(repository.findByToken(any())) .thenReturn(access); final String path = "/test/path"; final String token = "testToken"; assertThrows(HaltException.class, () ->new AccessService(repository).before(path, token)); then(repository).should().findByToken(any()); then(repository).shouldHaveNoMoreInteractions(); } @Test void given_newUser_when_createUser_should_storeNewUser() { final RegistrateRequest request = RegistrateRequest.of("testUser", "testPwd"); final AccessRepository repository = mock(AccessRepository.class); when(repository.findByUserName(any())) .thenReturn(null); ArgumentCaptor accessCaptor = ArgumentCaptor.forClass(Access.class); final AccessService service = new AccessService(repository); service.addObserver(this); final boolean result = service.createPlayer(request); assertTrue(result); assertThat("No event thrown", this.event, notNullValue()); verify(repository).save(accessCaptor.capture()); final Access createdAccess = accessCaptor.getValue(); assertNotNull(createdAccess, "No Access created"); assertNotNull(createdAccess.get_id(), "No Id created"); assertNotNull(createdAccess.getUserId(), "No UserId created"); assertEquals("testUser", createdAccess.getName(), "Wrong Username"); assertEquals("testPwd", createdAccess.getPassword(), "Wrong Password"); assertEquals(Role.USER.name(), createdAccess.getRole().name(), "Should be USER"); assertNull(createdAccess.getToken(), "User should not be logged in"); then(repository).should().findByUserName(any()); then(repository).should().save(any(Access.class)); then(repository).shouldHaveNoMoreInteractions(); } @Test void given_loggedInUser_when_logout_should_logoutUser() { final Access access = new Access( "testId", "testName", "testPwd", UserId.of("12345"), null, Role.USER ); final AccessToken token = AccessToken.of(access); access.setToken(token); final AccessRepository repository = mock(AccessRepository.class); when(repository.findByToken(any())) .thenReturn(access); ArgumentCaptor accessCaptor = ArgumentCaptor.forClass(Access.class); final AccessService service = new AccessService(repository); final boolean result = service.logout("testToken"); assertTrue(result); verify(repository).save(accessCaptor.capture()); final Access createdAccess = accessCaptor.getValue(); assertNotNull(createdAccess, "No Access created"); assertNotNull(createdAccess.get_id(), "No Id created"); assertNotNull(createdAccess.getUserId(), "No UserId created"); assertEquals("testName", createdAccess.getName(), "Wrong Username"); assertEquals("testPwd", createdAccess.getPassword(), "Wrong Password"); assertEquals(Role.USER.name(), createdAccess.getRole().name(), "Should be USER"); assertNull(createdAccess.getToken(), "User should logged out"); then(repository).should().findByToken(any()); then(repository).should().save(any(Access.class)); then(repository).shouldHaveNoMoreInteractions(); } @Test void given_storedUser_when_loginUser_should_returnLoginRequest() { final byte[] message = Base64.getEncoder().encode("testName:testPassword".getBytes()); final String header = "Basic " + new String(message); final Access access = new Access( "testId", "testName", "testPassword", UserId.of("12345"), null, Role.USER ); final AccessRepository repository = mock(AccessRepository.class); when(repository.findByUserName(any())) .thenReturn(access); final LoginRequest result = new AccessService(repository).authorization(header); assertNotNull(result); assertEquals(result.getName(), "testName", "Wrong UserName"); assertEquals(result.getUserId(), "12345", "Wrong Password"); assertNotNull(result.getToken(), "Not logged in"); } @Test void given_storedUserWithWrongPassword_when_loginUser_should_returnAccessDeny() { final byte[] message = Base64.getEncoder().encode("testName:testPassword".getBytes()); final String header = "Basic " + new String(message); final AccessRepository repository = mock(AccessRepository.class); final LoginRequest result = new AccessService(repository).authorization(header); assertNull(result, "Return LoginRequest but wrong permissions"); } @Test void given_storedUser_when_deleteUser_should_deleteUser() { final UserId userId = UserId.of("12345"); final AccessToken token = new AccessToken(null, null, null, UserId.of("12345")); final AccessRepository repository = mock(AccessRepository.class); when(repository.deleteLoginByUserId(any(UserId.class))) .thenReturn(new WriteResult(1, false, null)); final AccessService service = new AccessService(repository); service.addObserver(this); final boolean result = service.deleteAccount(userId, token); assertTrue(result); assertNotNull(event); then(repository).should().deleteLoginByUserId(any(UserId.class)); then(repository).shouldHaveNoMoreInteractions(); } @Test void given_storedUser_when_deleteUserWithWrongPermission_should_doNothing() { final UserId userId = UserId.of("12345"); final AccessToken token = new AccessToken(null, null, null, UserId.of("98765")); final AccessRepository repository = mock(AccessRepository.class); when(repository.deleteLoginByUserId(any(UserId.class))) .thenReturn(new WriteResult(1, false, null)); final AccessService service = new AccessService(repository); service.addObserver(this); final boolean result = service.deleteAccount(userId, token); assertFalse(result); assertNull(event); then(repository).shouldHaveNoInteractions(); } @Override public void update(Observable o, Object arg) { this.event = arg; } }