from __future__ import absolute_import

from mock import patch
from django.db import IntegrityError

from sentry.mediators.sentry_apps import Creator
from sentry.models import (
    AuditLogEntry,
    AuditLogEntryEvent,
    ApiApplication,
    IntegrationFeature,
    SentryApp,
    SentryAppComponent,
    User,
)
from sentry.testutils import TestCase


class TestCreator(TestCase):
    def setUp(self):
        self.user = self.create_user()
        self.org = self.create_organization(owner=self.user)
        self.creator = Creator(
            name="nulldb",
            user=self.user,
            author="Sentry",
            organization=self.org,
            scopes=("project:read",),
            webhook_url="http://example.com",
            schema={"elements": [self.create_issue_link_schema()]},
            is_internal=False,
        )

    def test_slug(self):
        app = self.creator.call()
        assert app.slug == "nulldb"

    def test_creates_proxy_user(self):
        self.creator.call()

        assert User.objects.get(username__contains="nulldb", is_sentry_app=True)

    def test_creates_api_application(self):
        self.creator.call()
        proxy = User.objects.get(username__contains="nulldb")

        assert ApiApplication.objects.get(owner=proxy)

    def test_creates_sentry_app(self):
        self.creator.call()

        proxy = User.objects.get(username__contains="nulldb")
        app = ApiApplication.objects.get(owner=proxy)

        sentry_app = SentryApp.objects.get(
            name="nulldb", application=app, owner=self.org, proxy_user=proxy
        )

        assert sentry_app
        assert sentry_app.scope_list == ["project:read"]

    def test_expands_rolled_up_events(self):
        self.creator.events = ["issue"]
        app = self.creator.call()

        sentry_app = SentryApp.objects.get(id=app.id)

        assert "issue.created" in sentry_app.events

    def test_creates_ui_components(self):
        self.creator.schema = {
            "elements": [self.create_issue_link_schema(), self.create_alert_rule_action_schema()]
        }

        app = self.creator.call()

        assert SentryAppComponent.objects.filter(sentry_app_id=app.id, type="issue-link").exists()

        assert SentryAppComponent.objects.filter(
            sentry_app_id=app.id, type="alert-rule-action"
        ).exists()

    def test_creates_integration_feature(self):
        app = self.creator.call()
        assert IntegrationFeature.objects.filter(sentry_app=app).exists()

    @patch("sentry.mediators.sentry_apps.creator.Creator.log")
    @patch("sentry.models.integrationfeature.IntegrationFeature.objects.create")
    def test_raises_error_creating_integration_feature(self, mock_create, mock_log):
        mock_create.side_effect = IntegrityError()
        self.creator.call()
        mock_log.assert_called_with(sentry_app="nulldb", error_message="")

    def test_creates_audit_log_entry(self):
        request = self.make_request(user=self.user, method="GET")
        Creator.run(
            name="nulldb",
            user=self.user,
            author="Sentry",
            organization=self.org,
            scopes=("project:read",),
            webhook_url="http://example.com",
            schema={"elements": [self.create_issue_link_schema()]},
            request=request,
            is_internal=False,
        )
        assert AuditLogEntry.objects.filter(event=AuditLogEntryEvent.SENTRY_APP_ADD).exists()

    def test_blank_schema(self):
        self.creator.schema = ""
        assert self.creator.call()

    def test_none_schema(self):
        self.creator.schema = None
        assert self.creator.call()

    def test_schema_with_no_elements(self):
        self.creator.schema = {"elements": []}
        assert self.creator.call()

    @patch("sentry.analytics.record")
    def test_records_analytics(self, record):
        sentry_app = Creator.run(
            name="nulldb",
            user=self.user,
            author="Sentry",
            organization=self.org,
            scopes=("project:read",),
            webhook_url="http://example.com",
            schema={"elements": [self.create_issue_link_schema()]},
            request=self.make_request(user=self.user, method="GET"),
            is_internal=False,
        )

        record.assert_called_with(
            "sentry_app.created",
            user_id=self.user.id,
            organization_id=self.org.id,
            sentry_app=sentry_app.slug,
        )

    def test_allows_name_that_exists_as_username_already(self):
        self.create_user(username="nulldb")
        assert self.creator.call()

[((2526, 2583), 'mock.patch', 'patch', (['"""sentry.mediators.sentry_apps.creator.Creator.log"""'], {}), "('sentry.mediators.sentry_apps.creator.Creator.log')\n", (2531, 2583), False, 'from mock import patch\n'), ((2589, 2664), 'mock.patch', 'patch', (['"""sentry.models.integrationfeature.IntegrationFeature.objects.create"""'], {}), "('sentry.models.integrationfeature.IntegrationFeature.objects.create')\n", (2594, 2664), False, 'from mock import patch\n'), ((3809, 3841), 'mock.patch', 'patch', (['"""sentry.analytics.record"""'], {}), "('sentry.analytics.record')\n", (3814, 3841), False, 'from mock import patch\n'), ((1030, 1095), 'sentry.models.User.objects.get', 'User.objects.get', ([], {'username__contains': '"""nulldb"""', 'is_sentry_app': '(True)'}), "(username__contains='nulldb', is_sentry_app=True)\n", (1046, 1095), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n'), ((1185, 1230), 'sentry.models.User.objects.get', 'User.objects.get', ([], {'username__contains': '"""nulldb"""'}), "(username__contains='nulldb')\n", (1201, 1230), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n'), ((1247, 1286), 'sentry.models.ApiApplication.objects.get', 'ApiApplication.objects.get', ([], {'owner': 'proxy'}), '(owner=proxy)\n', (1273, 1286), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n'), ((1372, 1417), 'sentry.models.User.objects.get', 'User.objects.get', ([], {'username__contains': '"""nulldb"""'}), "(username__contains='nulldb')\n", (1388, 1417), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n'), ((1432, 1471), 'sentry.models.ApiApplication.objects.get', 'ApiApplication.objects.get', ([], {'owner': 'proxy'}), '(owner=proxy)\n', (1458, 1471), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n'), ((1494, 1585), 'sentry.models.SentryApp.objects.get', 'SentryApp.objects.get', ([], {'name': '"""nulldb"""', 'application': 'app', 'owner': 'self.org', 'proxy_user': 'proxy'}), "(name='nulldb', application=app, owner=self.org,\n    proxy_user=proxy)\n", (1515, 1585), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n'), ((1830, 1862), 'sentry.models.SentryApp.objects.get', 'SentryApp.objects.get', ([], {'id': 'app.id'}), '(id=app.id)\n', (1851, 1862), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n'), ((2784, 2800), 'django.db.IntegrityError', 'IntegrityError', ([], {}), '()\n', (2798, 2800), False, 'from django.db import IntegrityError\n'), ((2150, 2224), 'sentry.models.SentryAppComponent.objects.filter', 'SentryAppComponent.objects.filter', ([], {'sentry_app_id': 'app.id', 'type': '"""issue-link"""'}), "(sentry_app_id=app.id, type='issue-link')\n", (2183, 2224), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n'), ((2250, 2336), 'sentry.models.SentryAppComponent.objects.filter', 'SentryAppComponent.objects.filter', ([], {'sentry_app_id': 'app.id', 'type': '"""alert-rule-action"""'}), "(sentry_app_id=app.id, type=\n    'alert-rule-action')\n", (2283, 2336), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n'), ((2461, 2510), 'sentry.models.IntegrationFeature.objects.filter', 'IntegrationFeature.objects.filter', ([], {'sentry_app': 'app'}), '(sentry_app=app)\n', (2494, 2510), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n'), ((3392, 3461), 'sentry.models.AuditLogEntry.objects.filter', 'AuditLogEntry.objects.filter', ([], {'event': 'AuditLogEntryEvent.SENTRY_APP_ADD'}), '(event=AuditLogEntryEvent.SENTRY_APP_ADD)\n', (3420, 3461), False, 'from sentry.models import AuditLogEntry, AuditLogEntryEvent, ApiApplication, IntegrationFeature, SentryApp, SentryAppComponent, User\n')]