<commit_before>package backend.Integration

import backend.model.user.UserService
import com.fasterxml.jackson.databind.ObjectMapper
import org.junit.Before
import org.junit.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*
import kotlin.test.assertEquals
import kotlin.test.assertNotNull

class TestUserEndpoint : IntegrationTest() {

    private fun url(): String = "/user/"

    private fun url(id: Int): String = "/user/${id.toString()}/"

    @Before
    override fun setUp() = super.setUp() // this will delete all users from the test database

    // TODO: Restricted Access based on roles

    /**
     * GET /user/
     */
    @Test
    fun getUser() {

        userService.create("<EMAIL>", "password", {
            firstname = "Florian"
            lastname = "Schmidt"
            gender = "Male"
        })

        userService.create("<EMAIL>", "password", {
            firstname = "Leo"
            lastname = "Theo"
            gender = "Male"
        })

        mockMvc.perform(get("/user/"))
                .andExpect(status().isOk)
                .andExpect(jsonPath("$").isArray)
                .andExpect(jsonPath("$[0].firstname").exists())
                .andExpect(jsonPath("$[0].lastname").exists())
                .andExpect(jsonPath("$[0].email").exists())
                .andExpect(jsonPath("$[0].gender").exists())
                .andExpect(jsonPath("$[0].passwordHash").doesNotExist())
                .andExpect(jsonPath("$[1].firstname").exists())
                .andExpect(jsonPath("$[1].lastname").exists())
                .andExpect(jsonPath("$[1].email").exists())
                .andExpect(jsonPath("$[1].gender").exists())
                .andExpect(jsonPath("$[1].passwordHash").doesNotExist())
    }

    @Test
    fun getAuthenticatedUser() {
        val credentials = createUser(this.mockMvc, userService = userService)

        val request = MockMvcRequestBuilders.get("/me/")
                .header("Authorization", "Bearer ${credentials.accessToken}")

        mockMvc.perform(request)
                .andExpect(status().isOk)
                .andExpect(jsonPath("$.id").exists())
                .andExpect(jsonPath("$.email").exists())
    }

    /**
     * POST /user/
     * Create user with email and password
     */
    @Test
    fun postUser() {

        val json = mapOf(
                "email" to "<EMAIL>",
                "password" to "password"
        ).toJsonString()

        mockMvc.perform(post(url(), json))
                .andExpect(status().isCreated)
                .andExpect(jsonPath("$.id").exists())

        val user = userRepository.findByEmail("<EMAIL>")
        assertNotNull(user)
        assertEquals(user.email, "<EMAIL>")
    }

    /**
     * POST /user/
     * Reject invalid email
     */
    @Test
    fun postUserRejectInvalidEmail() {

        val json = mapOf(
                "email" to "asd.de",
                "password" to "password"
        ).toJsonString()

        mockMvc.perform(post(url(), json))
                .andExpect(status().isBadRequest)
                .andExpect(content().string(""))
    }

    /**
     * POST /user/
     * Reject existing email
     */
    @Test
    fun postUserRejectExistingEmail() {
        val json = mapOf(
                "email" to "<EMAIL>",
                "password" to "password"
        ).toJsonString()

        mockMvc.perform(post(url(), json))
                .andExpect(status().isCreated)
                .andExpect(jsonPath("$.id").exists())


        mockMvc.perform(post(url(), json))
                .andExpect(status().isConflict)
                .andExpect(jsonPath("$.error").exists())
                .andExpect(jsonPath("$.error").value("user with email <EMAIL> already exists"))
    }

    /**
     * PUT /user/:id/
     * Modify the data of a user
     */
    @Test
    fun putUserId() {

        val credentials = createUser(this.mockMvc, userService = userService)

        // Update user
        val json = mapOf(
                "firstname" to "Florian",
                "lastname" to "Schmidt",
                "gender" to "Male",
                "blocked" to true
        ).toJsonString()

        val request = MockMvcRequestBuilders
                .put("/user/${credentials.id}/")
                .header("Authorization", "Bearer ${credentials.accessToken}")
                .contentType(MediaType.APPLICATION_JSON)
                .content(json)

        mockMvc.perform(request)
                .andExpect(status().isOk)
                .andExpect(jsonPath("$.id").value(credentials.id))
                .andExpect(jsonPath("$.email").value("<EMAIL>"))
                .andExpect(jsonPath("$.firstname").value("Florian"))
                .andExpect(jsonPath("$.lastname").value("Schmidt"))
                .andExpect(jsonPath("$.gender").value("Male"))
                .andExpect(jsonPath("$.blocked").value(false)) // Expect that a user can't block itself!

        // TODO: Check that some values such as passwordHash aren't shown!
        // TODO: Test response if user does not exist
        // TODO: Can't override existing properties with null!
    }

    @Test
    fun makeUserParticipant() {

        val credentials = createUser(this.mockMvc, userService = userService)

        // Update user with role participant
        val json = mapOf(
                "firstname" to "Florian",<commit_msg>Test that only authenticated user can modify its data<commit_after>package backend.Integration

import com.fasterxml.jackson.databind.ObjectMapper
import org.junit.Before
import org.junit.Test
import org.springframework.http.MediaType
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*
import kotlin.test.assertEquals
import kotlin.test.assertNotNull

class TestUserEndpoint : IntegrationTest() {

    private fun url(): String = "/user/"

    private fun url(id: Int): String = "/user/${id.toString()}/"

    @Before
    override fun setUp() = super.setUp()

    /**
     * GET /user/
     */
    @Test
    fun getUser() {

        userService.create("<EMAIL>", "password", {
            firstname = "Florian"
            lastname = "Schmidt"
            gender = "Male"
        })

        userService.create("<EMAIL>", "password", {
            firstname = "Leo"
            lastname = "Theo"
            gender = "Male"
        })

        mockMvc.perform(get("/user/"))
                .andExpect(status().isOk)
                .andExpect(jsonPath("$").isArray)
                .andExpect(jsonPath("$[0].firstname").exists())
                .andExpect(jsonPath("$[0].lastname").exists())
                .andExpect(jsonPath("$[0].email").exists())
                .andExpect(jsonPath("$[0].gender").exists())
                .andExpect(jsonPath("$[0].passwordHash").doesNotExist())
                .andExpect(jsonPath("$[1].firstname").exists())
                .andExpect(jsonPath("$[1].lastname").exists())
                .andExpect(jsonPath("$[1].email").exists())
                .andExpect(jsonPath("$[1].gender").exists())
                .andExpect(jsonPath("$[1].passwordHash").doesNotExist())
    }

    @Test
    fun getAuthenticatedUser() {
        val credentials = createUser(this.mockMvc, userService = userService)

        val request = MockMvcRequestBuilders.get("/me/")
                .header("Authorization", "Bearer ${credentials.accessToken}")

        mockMvc.perform(request)
                .andExpect(status().isOk)
                .andExpect(jsonPath("$.id").exists())
                .andExpect(jsonPath("$.email").exists())
    }

    /**
     * POST /user/
     * Create user with email and password
     */
    @Test
    fun postUser() {

        val json = mapOf(
                "email" to "<EMAIL>",
                "password" to "password"
        ).toJsonString()

        mockMvc.perform(post(url(), json))
                .andExpect(status().isCreated)
                .andExpect(jsonPath("$.id").exists())

        val user = userRepository.findByEmail("<EMAIL>")
        assertNotNull(user)
        assertEquals(user.email, "<EMAIL>")
    }

    /**
     * POST /user/
     * Reject invalid email
     */
    @Test
    fun postUserRejectInvalidEmail() {

        val json = mapOf(
                "email" to "asd.de",
                "password" to "password"
        ).toJsonString()

        mockMvc.perform(post(url(), json))
                .andExpect(status().isBadRequest)
                .andExpect(content().string(""))
    }

    /**
     * POST /user/
     * Reject existing email
     */
    @Test
    fun postUserRejectExistingEmail() {
        val json = mapOf(
                "email" to "<EMAIL>",
                "password" to "password"
        ).toJsonString()

        mockMvc.perform(post(url(), json))
                .andExpect(status().isCreated)
                .andExpect(jsonPath("$.id").exists())

        mockMvc.perform(post(url(), json))
                .andExpect(status().isConflict)
                .andExpect(jsonPath("$.error").exists())
                .andExpect(jsonPath("$.error").value("user with email <EMAIL> already exists"))
    }

    /**
     * PUT /user/:id/
     * Modify the data of a user
     */
    @Test
    fun putUserId() {

        val credentials = createUser(this.mockMvc, userService = userService)

        // Update user
        val json = mapOf(
                "firstname" to "Florian",
                "lastname" to "Schmidt",
                "gender" to "Male",
                "blocked" to true
        ).toJsonString()

        val request = MockMvcRequestBuilders
                .put("/user/${credentials.id}/")
                .header("Authorization", "Bearer ${credentials.accessToken}")
                .contentType(MediaType.APPLICATION_JSON)
                .content(json)

        mockMvc.perform(request)
                .andExpect(status().isOk)
                .andExpect(jsonPath("$.id").value(credentials.id))
                .andExpect(jsonPath("$.email").value("<EMAIL>"))
                .andExpect(jsonPath("$.firstname").value("Florian"))
                .andExpect(jsonPath("$.lastname").value("Schmidt"))
                .andExpect(jsonPath("$.gender").value("Male"))
                .andExpect(jsonPath("$.blocked").value(false)) // Expect that a user can't block itself!

        // TODO: Check that some values such as passwordHash aren't shown!
        // TODO: Test response if user does not exist
        // TODO: Can't override existing properties with null!
    }

    @Test
    fun putUserCanOnlyModifyItsOwnData() {
        val firstUserCredentials = createUser(this.mockMvc, "<EMAIL>", "pwd", this.userService)
        val secondUserCredentials = createUser(this.mockMvc, "<EMAIL>", "pwd", this.userService)

        val json = mapOf("firstname" to "ChangeMe").toJsonString()
        val request = MockMvcRequestBuilders
                .put("/user/${firstUserCredentials.id}/")
                .header("Authorization", "Bearer ${secondUserCredentials.accessToken}")
                .contentType(MediaType.APPLICATION_JSON)
                .content(json)
        mockMvc.perform(request).andExpect(status().isUnauthorized)
    }

    @Test
    fun putUserUnauthorizedUserCantModifyUserData() {
        val json = mapOf("firstname" to "ChangeMe").toJsonString()
        val request = MockMvcRequestBuilders.put("/user/1/")
                .contentType(MediaType.APPLICATION_JSON)
                .content(json)
        mockMvc.perform(request).andExpect(status().isUnauthorized)
    }

    @Test
    fun makeUserParticipant() {

        val credentials = createUser(this.mockMvc, userService = userService)

        // Update user with role participant
        val json = mapOf(
                "firstname" to "Florian",
{'fraction_non_alphanumeric': 0.14201624937821256, 'fraction_numerical': 0.001741004808489471, 'mean_word_length': 2.021793587174349, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3397327', 'n_tokens_mistral': 3461, 'n_tokens_neox': 3306, 'n_words': 622}