# -*- coding: utf-8 -*-

from __future__ import absolute_import

import mock

from exam import fixture

from sentry import options
from sentry.models import Project
from sentry.testutils import TestCase
from sentry.utils.http import (
    is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip,
)


class AbsoluteUriTest(TestCase):
    def test_without_path(self):
        assert absolute_uri() == options.get('system.url-prefix')

    def test_with_path(self):
        assert absolute_uri('/foo/bar') == '%s/foo/bar' % (options.get('system.url-prefix'),)


class SameDomainTestCase(TestCase):
    def test_is_same_domain(self):
        url1 = 'http://example.com/foo/bar'
        url2 = 'http://example.com/biz/baz'

        self.assertTrue(is_same_domain(url1, url2))

    def test_is_same_domain_diff_scheme(self):
        url1 = 'https://example.com/foo/bar'
        url2 = 'http://example.com/biz/baz'

        self.assertTrue(is_same_domain(url1, url2))

    def test_is_same_domain_diff_port(self):
        url1 = 'http://example.com:80/foo/bar'
        url2 = 'http://example.com:13/biz/baz'

        self.assertFalse(is_same_domain(url1, url2))


class GetOriginsTestCase(TestCase):
    def test_project_default(self):
        project = Project.objects.get()

        with self.settings(SENTRY_ALLOW_ORIGIN=None):
            result = get_origins(project)
            self.assertEquals(result, frozenset(['*']))

    def test_project(self):
        project = Project.objects.get()
        project.update_option('sentry:origins', [u'http://foo.example'])

        with self.settings(SENTRY_ALLOW_ORIGIN=None):
            result = get_origins(project)
            self.assertEquals(result, frozenset(['http://foo.example']))

    def test_project_and_setting(self):
        project = Project.objects.get()
        project.update_option('sentry:origins', [u'http://foo.example'])

        with self.settings(SENTRY_ALLOW_ORIGIN='http://example.com'):
            result = get_origins(project)
            self.assertEquals(result, frozenset(['http://foo.example', 'http://example.com']))

    def test_setting_empty(self):
        with self.settings(SENTRY_ALLOW_ORIGIN=None):
            result = get_origins(None)
            self.assertEquals(result, frozenset([]))

    def test_setting_all(self):
        with self.settings(SENTRY_ALLOW_ORIGIN='*'):
            result = get_origins(None)
            self.assertEquals(result, frozenset(['*']))

    def test_setting_uri(self):
        with self.settings(SENTRY_ALLOW_ORIGIN='http://example.com'):
            result = get_origins(None)
            self.assertEquals(result, frozenset(['http://example.com']))


class IsValidOriginTestCase(TestCase):
    @fixture
    def project(self):
        return mock.Mock()

    def isValidOrigin(self, origin, inputs):
        with mock.patch('sentry.utils.http.get_origins') as get_origins:
            get_origins.return_value = inputs
            result = is_valid_origin(origin, self.project)
            get_origins.assert_called_once_with(self.project)
        return result

    def test_global_wildcard_matches_domain(self):
        result = self.isValidOrigin('http://example.com', ['*'])
        self.assertEquals(result, True)

    def test_domain_wildcard_matches_domain(self):
        result = self.isValidOrigin('http://example.com', ['*.example.com'])
        self.assertEquals(result, True)

    def test_domain_wildcard_matches_domain_with_port(self):
        result = self.isValidOrigin('http://example.com:80', ['*.example.com'])
        self.assertEquals(result, True)

    def test_domain_wildcard_matches_subdomain(self):
        result = self.isValidOrigin('http://foo.example.com', ['*.example.com'])
        self.assertEquals(result, True)

    def test_domain_wildcard_matches_subdomain_with_port(self):
        result = self.isValidOrigin('http://foo.example.com:80', ['*.example.com'])
        self.assertEquals(result, True)

    def test_domain_wildcard_does_not_match_others(self):
        result = self.isValidOrigin('http://foo.com', ['*.example.com'])
        self.assertEquals(result, False)

    def test_domain_wildcard_matches_domain_with_path(self):
        result = self.isValidOrigin('http://foo.example.com/foo/bar', ['*.example.com'])
        self.assertEquals(result, True)

    def test_base_domain_matches_domain(self):
        result = self.isValidOrigin('http://example.com', ['example.com'])
        self.assertEquals(result, True)

    def test_base_domain_matches_domain_with_path(self):
        result = self.isValidOrigin('http://example.com/foo/bar', ['example.com'])
        self.assertEquals(result, True)

    def test_base_domain_matches_domain_with_port(self):
        result = self.isValidOrigin('http://example.com:80', ['example.com'])
        self.assertEquals(result, True)

    def test_base_domain_matches_domain_with_explicit_port(self):
        result = self.isValidOrigin('http://example.com:80', ['example.com:80'])
        assert result is True

    def test_base_domain_does_not_match_domain_with_invalid_port(self):
        result = self.isValidOrigin('http://example.com:80', ['example.com:443'])
        assert result is False

    def test_base_domain_does_not_match_subdomain(self):
        result = self.isValidOrigin('http://example.com', ['foo.example.com'])
        self.assertEquals(result, False)

    def test_full_uri_match(self):
        result = self.isValidOrigin('http://example.com', ['http://example.com'])
        self.assertEquals(result, True)

    def test_full_uri_match_requires_scheme(self):
        result = self.isValidOrigin('https://example.com', ['http://example.com'])
        self.assertEquals(result, False)

    def test_full_uri_match_does_not_require_port(self):
        result = self.isValidOrigin('http://example.com:80', ['http://example.com'])
        self.assertEquals(result, True)

    def test_partial_uri_match(self):
        result = self.isValidOrigin('http://example.com/foo/bar', ['http://example.com'])
        self.assertEquals(result, True)

    def test_null_valid_with_global(self):
        result = self.isValidOrigin('null', ['*'])
        self.assertEquals(result, True)

    def test_null_invalid_graceful_with_domains(self):
        result = self.isValidOrigin('null', ['http://example.com'])
        self.assertEquals(result, False)

    def test_custom_protocol_with_location(self):
        result = self.isValidOrigin('sp://custom-thing/foo/bar', ['sp://custom-thing'])
        assert result is True

        result = self.isValidOrigin('sp://custom-thing-two/foo/bar', ['sp://custom-thing'])
        assert result is False

    def test_custom_protocol_without_location(self):
        result = self.isValidOrigin('sp://custom-thing/foo/bar', ['sp://*'])
        assert result is True

        result = self.isValidOrigin('dp://custom-thing/foo/bar', ['sp://'])
        assert result is False

    def test_custom_protocol_with_domainish_match(self):
        result = self.isValidOrigin('sp://custom-thing.foobar/foo/bar', ['sp://*.foobar'])
        assert result is True

        result = self.isValidOrigin('sp://custom-thing.bizbaz/foo/bar', ['sp://*.foobar'])
        assert result is False

    def test_unicode(self):
        result = self.isValidOrigin(u'http://l\xf8calhost', [u'*.l\xf8calhost'])
        assert result is True

    def test_punycode(self):
        result = self.isValidOrigin('http://xn--lcalhost-54a', [u'*.l\xf8calhost'])
        assert result is True
        result = self.isValidOrigin('http://xn--lcalhost-54a', [u'*.xn--lcalhost-54a'])
        assert result is True
        result = self.isValidOrigin(u'http://l\xf8calhost', [u'*.xn--lcalhost-54a'])
        assert result is True
        result = self.isValidOrigin('http://l\xc3\xb8calhost', [u'*.xn--lcalhost-54a'])
        assert result is True
        result = self.isValidOrigin('http://xn--lcalhost-54a', [u'l\xf8calhost'])
        assert result is True
        result = self.isValidOrigin('http://xn--lcalhost-54a:80', [u'l\xf8calhost:80'])
        assert result is True

    def test_unparseable_uri(self):
        result = self.isValidOrigin('http://example.com', ['.'])
        assert result is False


class IsValidIPTestCase(TestCase):
    def is_valid_ip(self, ip, inputs):
        self.project.update_option('sentry:blacklisted_ips', inputs)
        return is_valid_ip(ip, self.project)

    def test_not_in_blacklist(self):
        assert self.is_valid_ip('127.0.0.1', [])
        assert self.is_valid_ip('127.0.0.1', ['0.0.0.0', '192.168.1.1', '10.0.0.0/8'])

    def test_match_blacklist(self):
        assert not self.is_valid_ip('127.0.0.1', ['127.0.0.1'])
        assert not self.is_valid_ip('127.0.0.1', ['0.0.0.0', '127.0.0.1', '192.168.1.1'])

    def test_match_blacklist_range(self):
        assert not self.is_valid_ip('127.0.0.1', ['127.0.0.0/8'])
        assert not self.is_valid_ip('127.0.0.1', ['0.0.0.0', '127.0.0.0/8', '192.168.1.0/8'])

[((1263, 1284), 'sentry.models.Project.objects.get', 'Project.objects.get', ([], {}), '()\n', (1282, 1284), False, 'from sentry.models import Project\n'), ((1485, 1506), 'sentry.models.Project.objects.get', 'Project.objects.get', ([], {}), '()\n', (1504, 1506), False, 'from sentry.models import Project\n'), ((1809, 1830), 'sentry.models.Project.objects.get', 'Project.objects.get', ([], {}), '()\n', (1828, 1830), False, 'from sentry.models import Project\n'), ((2781, 2792), 'mock.Mock', 'mock.Mock', ([], {}), '()\n', (2790, 2792), False, 'import mock\n'), ((8408, 8437), 'sentry.utils.http.is_valid_ip', 'is_valid_ip', (['ip', 'self.project'], {}), '(ip, self.project)\n', (8419, 8437), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((397, 411), 'sentry.utils.http.absolute_uri', 'absolute_uri', ([], {}), '()\n', (409, 411), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((415, 447), 'sentry.options.get', 'options.get', (['"""system.url-prefix"""'], {}), "('system.url-prefix')\n", (426, 447), False, 'from sentry import options\n'), ((494, 518), 'sentry.utils.http.absolute_uri', 'absolute_uri', (['"""/foo/bar"""'], {}), "('/foo/bar')\n", (506, 518), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((759, 785), 'sentry.utils.http.is_same_domain', 'is_same_domain', (['url1', 'url2'], {}), '(url1, url2)\n', (773, 785), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((949, 975), 'sentry.utils.http.is_same_domain', 'is_same_domain', (['url1', 'url2'], {}), '(url1, url2)\n', (963, 975), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((1143, 1169), 'sentry.utils.http.is_same_domain', 'is_same_domain', (['url1', 'url2'], {}), '(url1, url2)\n', (1157, 1169), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((1361, 1381), 'sentry.utils.http.get_origins', 'get_origins', (['project'], {}), '(project)\n', (1372, 1381), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((1656, 1676), 'sentry.utils.http.get_origins', 'get_origins', (['project'], {}), '(project)\n', (1667, 1676), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((1996, 2016), 'sentry.utils.http.get_origins', 'get_origins', (['project'], {}), '(project)\n', (2007, 2016), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((2222, 2239), 'sentry.utils.http.get_origins', 'get_origins', (['None'], {}), '(None)\n', (2233, 2239), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((2400, 2417), 'sentry.utils.http.get_origins', 'get_origins', (['None'], {}), '(None)\n', (2411, 2417), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((2598, 2615), 'sentry.utils.http.get_origins', 'get_origins', (['None'], {}), '(None)\n', (2609, 2615), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((2852, 2895), 'mock.patch', 'mock.patch', (['"""sentry.utils.http.get_origins"""'], {}), "('sentry.utils.http.get_origins')\n", (2862, 2895), False, 'import mock\n'), ((2979, 3016), 'sentry.utils.http.is_valid_origin', 'is_valid_origin', (['origin', 'self.project'], {}), '(origin, self.project)\n', (2994, 3016), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((3029, 3078), 'sentry.utils.http.get_origins.assert_called_once_with', 'get_origins.assert_called_once_with', (['self.project'], {}), '(self.project)\n', (3064, 3078), False, 'from sentry.utils.http import is_same_domain, is_valid_origin, get_origins, absolute_uri, is_valid_ip\n'), ((538, 570), 'sentry.options.get', 'options.get', (['"""system.url-prefix"""'], {}), "('system.url-prefix')\n", (549, 570), False, 'from sentry import options\n')]