package net.m4e.app.user;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.revinate.assertj.json.JsonPathAssert;
import net.m4e.app.auth.AuthorityConfig;
import net.m4e.app.resources.StatusEntity;
import net.m4e.common.ResponseResults;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.*;

/**
 * @author ybroeker
 */
class UserAuthenticationFacadeRESTTest {

    private final static String EXISTING_USER = "testuser";
    private final static String NON_EXISTING_USER = "nonexisting";
    private final static String PASSWORD = "password";


    private final static String RIGHT_CREDENTIALS = String.format("{\"login\":\"%s\", \"password\":\"%s\"}", EXISTING_USER, PASSWORD);

    @Mock
    Users users;
    @Mock
    HttpServletRequest request;
    @Mock
    HttpSession session;

    UserAuthenticationFacadeREST userAuthentication;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.initMocks(this);

        Mockito.when(session.getId()).thenReturn("0");

        Mockito.when(request.getSession()).thenReturn(session);
        userAuthentication = new UserAuthenticationFacadeREST(users);

        UserEntity userEntity = new UserEntity();
        userEntity.setStatus(new StatusEntity());
        userEntity.setPassword(AuthorityConfig.getInstance().createPassword(PASSWORD));
        userEntity.setLogin(EXISTING_USER);
        userEntity.setId(1L);
        Mockito.when(users.findUser(EXISTING_USER)).thenReturn(userEntity);
        Mockito.when(users.findUser(NON_EXISTING_USER)).thenReturn(null);
    }

    @NotNull
    private JsonPathAssert assertThat(@Nullable String string) {
        if (string == null) {
            string = "";
        }
        DocumentContext ctx = JsonPath.parse(string);
        return com.revinate.assertj.json.JsonPathAssert.assertThat(ctx);
    }


    @Test
    void login_rightCredentials() {
        String input = RIGHT_CREDENTIALS;


        String response = userAuthentication.login(input, request);


        assertThat(response).jsonPathAsString("$.code").isEqualTo(Integer.toString(ResponseResults.CODE_OK));
    }

    @Test
    void login_wrongCredentials() {
        String input = "{\"login\":\"testuser\", \"password\":\"wrongpassword\"}";


        String response = userAuthentication.login(input, request);


        assertThat(response).jsonPathAsString("$.code").isEqualTo(Integer.toString(ResponseResults.CODE_UNAUTHORIZED));
    }

    @Test
    void login_alreadyLoggedInUser() {
        String input = RIGHT_CREDENTIALS;
        Mockito.when(session.getAttribute(AuthorityConfig.SESSION_ATTR_USER)).thenReturn(new Object());

        String response = userAuthentication.login(input, request);


        assertThat(response).jsonPathAsString("$.code").isEqualTo(Integer.toString(ResponseResults.CODE_NOT_ACCEPTABLE));
    }

    @Test
    void login_nonExistingUser() {
        String input = "{\"login\":\"nonexisting\", \"password\":\"password\"}";


        String response = userAuthentication.login(input, request);


        assertThat(response).jsonPathAsString("$.code").isEqualTo(Integer.toString(ResponseResults.CODE_NOT_FOUND));
    }

    @Test
    void login_invalidInput() {
        String input = "{\"password\":\"password\"}";


        String response = userAuthentication.login(input, request);


        assertThat(response).jsonPathAsString("$.code").isEqualTo(Integer.toString(ResponseResults.CODE_BAD_REQUEST));
    }

    @Test
    void login_emptyInput() {
        String input = "";


        String response = userAuthentication.login(input, request);


        assertThat(response).jsonPathAsString("$.code").isEqualTo(Integer.toString(ResponseResults.CODE_BAD_REQUEST));
    }


}

@@ -792,24 +792,83 @@
 password%22;%0A%0A
+    private final static String SESSION_ID = %22session_id%22;%0A
 %0A    private
@@ -980,24 +980,50 @@
 G_USER, 
-PASSWORD
+hashPassword(PASSWORD, SESSION_ID)
 );%0A%0A    
@@ -1310,11 +1310,18 @@
 urn(
-%220%22
+SESSION_ID
 );%0A%0A
@@ -1870,24 +1870,253 @@
 ll);%0A    %7D%0A%0A
+    private static String hashPassword(String plainPassword, String salt) %7B%0A        return AuthorityConfig.getInstance().createPassword(%0A                AuthorityConfig.getInstance().createPassword(plainPassword) + salt);%0A    %7D%0A%0A
     @NotNull
@@ -2772,21 +2772,45 @@
 %22:%5C%22
-wrongpassword
+%22 + hashPassword(%22wrong%22, %22salt%22) + %22
 %5C%22%7D%22

Fix UserAuth-Test