<commit_before>"""Custom User model tests."""
# Copyright 2015 Solinea, Inc.
#
# Licensed under the Solinea Software License Agreement (goldstone),
# Version 1.0 (the "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at:
#
#     http://www.solinea.com/goldstone/LICENSE.pdf
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
from django.contrib.auth import get_user_model
from django.test import SimpleTestCase, Client
from rest_framework.status import HTTP_200_OK, HTTP_401_UNAUTHORIZED

# Http response content that are expected by some tests.
CONTENT_NO_CREDENTIALS = \
    '{"detail":"Authentication credentials were not provided."}'
CONTENT_BAD_TOKEN = '{"detail":"Invalid token"}'

# Define the URLs and payloads used in this module's testing.
LOGIN_URL = "/accounts/login"
USER_URL = "/user"
AUTHORIZATION_PAYLOAD = "Token %s"


def _create_and_login():
    """Create a user and log them in.

    :return: The authorization token's value
    :rtype: str

    """

    # Create a user
    get_user_model().objects.create_user("fred", "<EMAIL>", "meh")

    # Log the user in, and return the auth token's value.
    client = Client()
    response = client.post(LOGIN_URL, {"username": "fred", "password": "<PASSWORD>"})

    assert response.status_code == HTTP_200_OK

    return response.data["auth_token"]      # pylint: disable=E1101


class NoAccess(SimpleTestCase):
    """The user attempts access without being logged in, or presenting a bad
    authentication token."""

    def setUp(self):
        """Do some housekeeping before each test."""

        # SimpleTestCase doesn't always reset the database to as much of an
        # initial state as we expect. So, do it explicitly.
        get_user_model().objects.all().delete()

    def test_get_nologin(self):
        """Getting while not logged in."""

        EXPECTED_CONTENT = CONTENT_NO_CREDENTIALS

        client = Client()
        response = client.get(USER_URL)

        self.assertContains(response,
                            EXPECTED_CONTENT,
                            status_code=HTTP_401_UNAUTHORIZED)

    def test_get_badtoken(self):
        """Getting while not logged in, using any token."""

        BAD_TOKEN = "2<PASSWORD>"
        EXPECTED_CONTENT = CONTENT_BAD_TOKEN

        client = Client()
        response = \
            client.get(USER_URL,
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            EXPECTED_CONTENT,
                            status_code=HTTP_401_UNAUTHORIZED)

    def test_loggedin_get_badtoken(self):
        """Getting while logged in, using a bad token."""

        EXPECTED_CONTENT = CONTENT_BAD_TOKEN

        # Create a user, and create a bad authorization token.  (This test will
        # erroneously fail if the good token doesn't contain any 9 characters,
        # which is very unlikely.)
        bad_token = _create_and_login().replace('9', '8')

        client = Client()
        response = \
            client.get(USER_URL,
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % bad_token)

        self.assertContains(response,
                            EXPECTED_CONTENT,
                            status_code=HTTP_401_UNAUTHORIZED)

    def test_put_nologin(self):
        """Putting (trying to change user attributes) while not logged in."""

        EXPECTED_CONTENT = CONTENT_NO_CREDENTIALS

        client = Client()
        response = client.put(USER_URL, {"first_name": "Dirk"})

        self.assertContains(response,
                            EXPECTED_CONTENT,
                            status_code=HTTP_401_UNAUTHORIZED)

    def test_put_badtoken(self):
        """Putting (trying to change user attributes) while logged in, but
        using a bad token."""

        EXPECTED_CONTENT = CONTENT_BAD_TOKEN

        # Create a user, and create a bad authorization token.
        bad_token = _create_and_login().replace('9', '8')

        client = Client()
        response = \
            client.put(USER_URL,
                       {"first_name": "Dirk"},
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % bad_token)

        self.assertContains(response,
                            EXPECTED_CONTENT,
                            status_code=HTTP_401_UNAUTHORIZED)


class Get(SimpleTestCase):
    """The user gets her account's User data."""

    def setUp(self):
        """Do some housekeeping before each test."""

        # SimpleTestCase doesn't always reset the database to as much of an
        # initial state as we expect. So, do it explicitly.
        get_user_model().objects.all().delete()

    def test_get(self):
        """Get data from the default created account."""

        expected_content = {"username": "fred",
                            "first_name": '',
                            "last_name": '',
                            "email": "<EMAIL>",
                            "tenant_admin": False,
                            "default_tenant_admin": False}

        # Create a user and get their authorization token.
        token = _create_and_login()

        client = Client()
        response = \
            client.get(USER_URL,
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, HTTP_200_OK)

        # We deserialize the response content, to simplify checking the
        # results. We'll check that the uuid key is present, and it has a
        # string value, but we don't check the value.
        response_content = json.loads(response.content)
        for key in expected_content:
            self.assertEqual(response_content[key], expected_content[key])
        self.assertEqual(len(response_content), len(expected_content) + 1)
        self.assertIn("uuid", response_content)
        self.assertIsInstance(response_content["uuid"], basestring)

    def test_get_changed_fields(self):
        """Get data from the created account, after we've modified it."""

        pass


# class Put(SimpleTestCase):
#     pass


# class BadPut(SimpleTestCase):
#     pass
<commit_msg>GOLD-639: More User tests, including changing account attributes.<commit_after>"""Custom User model tests."""
# Copyright 2015 Solinea, Inc.
#
# Licensed under the Solinea Software License Agreement (goldstone),
# Version 1.0 (the "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at:
#
#     http://www.solinea.com/goldstone/LICENSE.pdf
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
from django.contrib.auth import get_user_model
from django.test import SimpleTestCase, Client
from rest_framework.status import HTTP_200_OK, HTTP_401_UNAUTHORIZED

# Http response content that are expected by some tests.
CONTENT_NO_CREDENTIALS = \
    '{"detail":"Authentication credentials were not provided."}'
CONTENT_BAD_TOKEN = '{"detail":"Invalid token"}'

# Define the URLs and payloads used in this module's testing.
LOGIN_URL = "/accounts/login"
USER_URL = "/user"
AUTHORIZATION_PAYLOAD = "Token %s"
TEST_USER = ("fred", "<EMAIL>", "meh")
TEST_USER_LOGIN = {"username": TEST_USER[0], "password": <PASSWORD>[2]}


def _create_and_login():
    """Create a user and log them in.

    :return: The authorization token's value
    :rtype: str

    """

    # Create a user
    get_user_model().objects.create_user(*TEST_USER)

    # Log the user in, and return the auth token's value.
    client = Client()
    response = client.post(LOGIN_URL, TEST_USER_LOGIN)

    assert response.status_code == HTTP_200_OK

    return response.data["auth_token"]      # pylint: disable=E1101


def _response_equals_without_uuid(response, expected_status_code,
                                  expected_content):
    """Compare a response's content with expected content, without fully
    testing the "uuid" key.

    This module's tests can't always just do a self.assertContains, or use
    self.assertEqual, because the response contains a "uuid" key. We want to
    test that the uuid key is present and its value is a string, without
    comparing the uuid strings.

    :param response: The HTTP response to be tested
    :type response: django.test.client.Response
    :param expected_status_code: The expected status code
    :type expected_status_code: rest_framework.status.HTTP*
    :param expected_content: The expected response.content
    :type expected_content: dict

    """

    assert response.status_code == expected_status_code

    # We deserialize the response content, to simplify checking the
    # results
    response_content = json.loads(response.content)

    # Check that every expected key is in the response, and the content lengths
    # differ by only one.
    for key in expected_content:
        assert response_content[key] == expected_content[key]

    assert len(response_content) == len(expected_content) + 1

    # Verify that the uuid key is present and its value is a string, but
    # don't check the value's content.
    assert "uuid" in response_content
    assert isinstance(response_content["uuid"], basestring)


class Setup(SimpleTestCase):

    """A base class to ensure we do needed housekeeping before each test."""

    def setUp(self):
        """Do explicit database reseting because SimpleTestCase doesn't always
        reset the database to as much of an initial state as we expect."""

        get_user_model().objects.all().delete()


class NoAccess(Setup):
    """The user attempts access without being logged in, or presenting a bad
    authentication token."""

    def test_get_nologin(self):
        """Getting while not logged in."""

        EXPECTED_CONTENT = CONTENT_NO_CREDENTIALS

        client = Client()
        response = client.get(USER_URL)

        self.assertContains(response,
                            EXPECTED_CONTENT,
                            status_code=HTTP_401_UNAUTHORIZED)

    def test_get_badtoken(self):
        """Getting while not logged in, using any token."""

        BAD_TOKEN = "2<PASSWORD>"
        EXPECTED_CONTENT = CONTENT_BAD_TOKEN

        client = Client()
        response = \
            client.get(USER_URL,
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            EXPECTED_CONTENT,
                            status_code=HTTP_401_UNAUTHORIZED)

    def test_loggedin_get_badtoken(self):
        """Getting while logged in, using a bad token."""

        EXPECTED_CONTENT = CONTENT_BAD_TOKEN

        # Create a user, and create a bad authorization token.  (This test will
        # erroneously fail if the good token doesn't contain any 9 characters,
        # which is very unlikely.)
        bad_token = _create_and_login().replace('9', '8')

        client = Client()
        response = \
            client.get(USER_URL,
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % bad_token)

        self.assertContains(response,
                            EXPECTED_CONTENT,
                            status_code=HTTP_401_UNAUTHORIZED)

    def test_put_nologin(self):
        """Putting (trying to change user attributes) while not logged in."""

        EXPECTED_CONTENT = CONTENT_NO_CREDENTIALS

        client = Client()
        response = client.put(USER_URL, {"first_name": "Dirk"})

        self.assertContains(response,
                            EXPECTED_CONTENT,
                            status_code=HTTP_401_UNAUTHORIZED)

    def test_put_badtoken(self):
        """Putting (trying to change user attributes) while logged in, but
        using a bad token."""

        EXPECTED_CONTENT = CONTENT_BAD_TOKEN

        # Create a user, and create a bad authorization token.
        bad_token = _create_and_login().replace('9', '8')

        client = Client()
        response = \
            client.put(USER_URL,
                       {"first_name": "Dirk"},
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % bad_token)

        self.assertContains(response,
                            EXPECTED_CONTENT,
                            status_code=HTTP_401_UNAUTHORIZED)


class GetPut(Setup):
    """The user gets her account's User data, and changes some attributes."""

    def test_get(self):                   # pylint: disable=R0201
        """Get data from the default created account."""

        expected_content = {"username": TEST_USER[0],
                            "first_name": '',
                            "last_name": '',
                            "email": TEST_USER[1],
                            "tenant_admin": False,
                            "default_tenant_admin": False}

        # Create a user and get their authorization token.
        token = _create_and_login()

        client = Client()
        response = \
            client.get(USER_URL,
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        _response_equals_without_uuid(response, HTTP_200_OK, expected_content)

    def test_change_one_field(self):
        """Change one field in the account."""

        expected_content = {"username": TEST_USER[0],
                            "first_name": "Dirk",
                            "last_name": '',
                            "email": TEST_USER[1],
                            "tenant_admin": False,
                            "default_tenant_admin": False}

        # Create a user and get their authorization token.
        token = _create_and_login()

        # Change some attributes from the default. Note, the username is
        # required by djoser UserView/PUT.
        client = Client()
        response = \
            client.put(USER_URL,
                       json.dumps({"username": TEST_USER[0],
                                   "first_name": "Dirk"}),
                       content_type="application/json",
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, HTTP_200_OK)

        # Now get the account attributes and see if they've changed.
        response = \
            client.get(USER_URL,
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        _response_equals_without_uuid(response, HTTP_200_OK, expected_content)

    def test_change_some_fields(self):
        """Get data from an account, after we've modified some fields."""

        expected_content = {"username": TEST_USER[0],
                            "first_name": "Dirk",
                            "last_name": "Diggler",
                            "email": TEST_USER[1],
                            "tenant_admin": False,
                            "default_tenant_admin": False}

        # Create a user and get their authorization token.
        token = _create_and_login()

        # Change some attributes from the default. Note, the username is
        # required by djoser UserView/PUT.
        client = Client()
        response = \
            client.put(USER_URL,
                       json.dumps({"username": TEST_USER[0],
                                   "first_name": "Dirk",
                                   "last_name": "Diggler"}),
                       content_type="application/json",
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, HTTP_200_OK)

        # Now get the account attributes and see if they've changed.
        response = \
            client.get(USER_URL,
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        _response_equals_without_uuid(response, HTTP_200_OK, expected_content)

    def test_change_all_fields(self):
        """Get data from an account, after we've modified all the
        user-modifyable fields."""

        expected_content = {"username": "Heywood",
                            "first_name": "Dirk",
                            "last_name": "Diggler",
                            "email": "<EMAIL>",
                            "tenant_admin": False,
                            "default_tenant_admin": False}

        # Create a user and get their authorization token.
        token = _create_and_login()

        # Change some attributes from the default. Note, the username is
        # required by djoser UserView/PUT.
        client = Client()
        response = \
            client.put(USER_URL,
                       json.dumps({"username": "Heywood",
                                   "first_name": "Dirk",
                                   "last_name": "Diggler",
                                   "email": "<EMAIL>"}),
                       content_type="application/json",
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, HTTP_200_OK)

        # Now get the account attributes and see if they've changed.
        response = \
            client.get(USER_URL,
                       HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        _response_equals_without_uuid(response, HTTP_200_OK, expected_content)


# class BadPut(Setup):
#     pass

{'fraction_non_alphanumeric': 0.0845536666105594, 'fraction_numerical': 0.006901195085002525, 'mean_word_length': 2.1965566714490676, 'pattern_counts': {'":': 51, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 7, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5864977', 'n_tokens_mistral': 4885, 'n_tokens_neox': 4659, 'n_words': 1383}