Ejemplo n.º 1
0
    def form_valid(self, form):
        from .type import RocketChatType

        base_url = form.cleaned_data["base_url"]
        config = {
            RocketChatType.CONFIG_BASE_URL: base_url,
            RocketChatType.CONFIG_SECRET: form.cleaned_data["secret"],
            RocketChatType.CONFIG_ADMIN_AUTH_TOKEN: form.cleaned_data["admin_auth_token"],
            RocketChatType.CONFIG_ADMIN_USER_ID: form.cleaned_data["admin_user_id"],
        }

        rc_host = urlparse(base_url).netloc

        self.object = Ticketer(
            uuid=uuid4(),
            org=self.org,
            ticketer_type=RocketChatType.slug,
            config=config,
            name=rc_host,
            created_by=self.request.user,
            modified_by=self.request.user,
        )

        client = Client(config[RocketChatType.CONFIG_BASE_URL], config[RocketChatType.CONFIG_SECRET])
        webhook_url = WEBHOOK_URL_TEMPLATE.format(domain=self.object.org.get_brand_domain(), uuid=self.object.uuid)

        try:
            client.settings(webhook_url)
            self.request.session.pop(self.SESSION_KEY, None)
        except ClientError as err:
            messages.error(self.request, err.msg if err.msg else _("Configuration has failed"))
            return super().get(self.request, *self.args, **self.kwargs)

        self.object.save()
        return super().form_valid(form)
Ejemplo n.º 2
0
    def test_is_available_to(self):
        self.assertTrue(InternalType().is_available_to(self.admin))

        Ticketer.create(org=self.org,
                        user=self.admin,
                        ticketer_type=InternalType.slug,
                        config={},
                        name=f"Internal")

        # not if they already created one
        self.assertFalse(InternalType().is_available_to(self.admin))
Ejemplo n.º 3
0
    def test_is_available_to(self):
        self.assertFalse(InternalType().is_available_to(self.admin))

        # only beta users see this
        Group.objects.get(name="Beta").user_set.add(self.admin)

        self.assertTrue(InternalType().is_available_to(self.admin))

        Ticketer.create(org=self.org,
                        user=self.admin,
                        ticketer_type=InternalType.slug,
                        config={},
                        name=f"Internal")

        # and not if they already created one
        self.assertFalse(InternalType().is_available_to(self.admin))
Ejemplo n.º 4
0
    def test_ticketer(self):
        t1 = Ticketer.create(self.org, self.admin, MailgunType.slug,
                             "Email ([email protected])", {})
        t2 = Ticketer.create(self.org, self.admin, MailgunType.slug,
                             "Old Email", {})
        t2.is_active = False
        t2.save()

        # create some logs
        l1 = HTTPLog.objects.create(
            ticketer=t1,
            url="http://org1.bar/zap",
            request="GET /zap",
            response=" OK 200",
            is_error=False,
            log_type=HTTPLog.TICKETER_CALLED,
            request_time=10,
            org=self.org,
        )

        list_url = reverse("request_logs.httplog_ticketer", args=[t1.uuid])
        log_url = reverse("request_logs.httplog_read", args=[l1.id])

        response = self.assertListFetch(list_url,
                                        allow_viewers=False,
                                        allow_editors=False,
                                        allow_org2=False,
                                        context_objects=[l1])
        self.assertContains(response, "Ticketing Service Called")
        self.assertContains(response, log_url)

        # view the individual log item
        response = self.assertReadFetch(log_url,
                                        allow_viewers=False,
                                        allow_editors=False,
                                        context_object=l1)
        self.assertContains(response, "200")
        self.assertContains(response, "http://org1.bar/zap")
        self.assertNotContains(response, "http://org2.bar/zap")

        # can't list logs for deleted ticketer
        response = self.requestView(
            reverse("request_logs.httplog_ticketer", args=[t2.uuid]),
            self.admin)
        self.assertEqual(404, response.status_code)
Ejemplo n.º 5
0
    def test_queue_broadcast(self):
        jim = self.create_contact("Jim", phone="+12065551212")
        bobs = self.create_group(
            "Bobs", [self.create_contact("Bob", phone="+12065551313")])
        ticketer = Ticketer.create(self.org, self.admin, "mailgun",
                                   "Support Tickets", {})
        ticket = self.create_ticket(ticketer, jim, "Help!")

        bcast = Broadcast.create(
            self.org,
            self.admin,
            {
                "eng": "Welcome to mailroom!",
                "spa": "¡Bienvenidx a mailroom!"
            },
            groups=[bobs],
            contacts=[jim],
            urns=["tel:+12065556666"],
            base_language="eng",
            ticket=ticket,
        )

        bcast.send_async()

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "send_broadcast",
                "org_id": self.org.id,
                "task": {
                    "translations": {
                        "eng": {
                            "text": "Welcome to mailroom!"
                        },
                        "spa": {
                            "text": "\u00a1Bienvenidx a mailroom!"
                        },
                    },
                    "template_state": "legacy",
                    "base_language": "eng",
                    "urns": ["tel:+12065556666"],
                    "contact_ids": [jim.id],
                    "group_ids": [bobs.id],
                    "broadcast_id": bcast.id,
                    "org_id": self.org.id,
                    "ticket_id": ticket.id,
                },
                "queued_on": matchers.ISODate(),
            },
        )
Ejemplo n.º 6
0
 def new_ticketer(self, config=None) -> Ticketer:
     return Ticketer.create(
         org=self.org, user=self.user, ticketer_type=RocketChatType.slug, name="Name", config=config or {}
     )
Ejemplo n.º 7
0
class ConnectView(BaseConnectView):
    SESSION_KEY = "_ticketer_rocketchat_secret"

    _secret = None

    class Form(BaseConnectView.Form):
        base_url = ExternalURLField(
            label=_("URL"),
            widget=forms.URLInput(
                attrs={
                    "placeholder": _(
                        "Ex.: https://my.rocket.chat/api/apps/public/51c5cebe-b8e4-48ae-89d3-2b7746019cc4"
                    )
                }
            ),
            help_text=_("URL of the Rocket.Chat Tickets app"),
        )
        admin_user_id = forms.CharField(label=_("Admin User ID"), help_text=_("User ID of an administrator user"))
        admin_auth_token = forms.CharField(
            label=_("Admin Auth Token"), help_text=_("Authentication token of an administrator user")
        )
        secret = forms.CharField(
            label=_("Secret"), widget=forms.HiddenInput(), help_text=_("Secret to be passed to Rocket.Chat")
        )

        def clean(self):
            secret = self.cleaned_data.get("secret")
            if not secret:
                raise forms.ValidationError(_("Invalid secret code."))

            initial = self.initial.get("secret")
            if secret != initial:
                self.data = self.data.copy()
                self.data["secret"] = initial
                raise forms.ValidationError(_("Secret code change detected."))
            return self.cleaned_data

        def clean_base_url(self):
            from .type import RocketChatType

            org = self.request.user.get_org()
            base_url = RE_BASE_URL.search(self.cleaned_data.get("base_url") or "")
            if base_url:
                base_url = base_url.group()
            else:
                raise forms.ValidationError(_("Invalid URL: %(base_url)s") % self.cleaned_data)

            base_url_exists = org.ticketers.filter(
                is_active=True,
                ticketer_type=RocketChatType.slug,
                **{f"config__{RocketChatType.CONFIG_BASE_URL}": base_url},
            ).exists()
            if base_url_exists:
                raise forms.ValidationError(_("There is already a ticketing service configured for this URL."))

            return base_url

    def get_secret(self):
        if self._secret:
            return self._secret

        self._secret = self.request.session.get(self.SESSION_KEY)
        if not self._secret or self.request.method.lower() != "post":
            self.request.session[self.SESSION_KEY] = self._secret = random_string(SECRET_LENGTH)
        return self._secret

    def derive_initial(self):
        initial = super().derive_initial()
        initial["secret"] = self.get_secret()
        return initial

    def form_valid(self, form):
        from .type import RocketChatType

        base_url = form.cleaned_data["base_url"]
        config = {
            RocketChatType.CONFIG_BASE_URL: base_url,
            RocketChatType.CONFIG_SECRET: form.cleaned_data["secret"],
            RocketChatType.CONFIG_ADMIN_AUTH_TOKEN: form.cleaned_data["admin_auth_token"],
            RocketChatType.CONFIG_ADMIN_USER_ID: form.cleaned_data["admin_user_id"],
        }

        rc_host = urlparse(base_url).netloc

        self.object = Ticketer(
            uuid=uuid4(),
            org=self.org,
            ticketer_type=RocketChatType.slug,
            config=config,
            name=rc_host,
            created_by=self.request.user,
            modified_by=self.request.user,
        )

        client = Client(config[RocketChatType.CONFIG_BASE_URL], config[RocketChatType.CONFIG_SECRET])
        webhook_url = WEBHOOK_URL_TEMPLATE.format(domain=self.object.org.get_brand_domain(), uuid=self.object.uuid)

        try:
            client.settings(webhook_url)
            self.request.session.pop(self.SESSION_KEY, None)
        except ClientError as err:
            messages.error(self.request, err.msg if err.msg else _("Configuration has failed"))
            return super().get(self.request, *self.args, **self.kwargs)

        self.object.save()
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        kwargs["secret"] = self.get_secret()
        return super().get_context_data(**kwargs)

    form_class = Form
    template_name = "tickets/types/rocketchat/connect.haml"
Ejemplo n.º 8
0
    def test_ticketer(self):
        self.customer_support.is_staff = True
        self.customer_support.save()

        # create some ticketers
        t1 = Ticketer.create(self.org, self.admin, MailgunType.slug,
                             "Email ([email protected])", {})
        t2 = Ticketer.create(self.org, self.admin, MailgunType.slug,
                             "Old Email", {})
        t2.is_active = False
        t2.save()

        list_url = reverse("request_logs.httplog_ticketer", args=[t1.uuid])
        response = self.client.get(list_url)
        self.assertLoginRedirect(response)

        # even admins can't view ticketer logs
        self.login(self.admin)
        response = self.client.get(list_url)
        self.assertLoginRedirect(response)

        # customer support can
        self.login(self.customer_support)
        response = self.client.get(list_url)
        self.assertEqual(200, response.status_code)

        # create some logs
        l1 = HTTPLog.objects.create(
            ticketer=t1,
            url="http://org1.bar/zap",
            request="GET /zap",
            response=" OK 200",
            is_error=False,
            log_type=HTTPLog.TICKETER_CALLED,
            request_time=10,
            org=self.org,
        )

        response = self.client.get(list_url)
        self.assertEqual(1, len(response.context["object_list"]))
        self.assertContains(response, "Ticketing Service Called")

        log_url = reverse("request_logs.httplog_read", args=[l1.id])
        self.assertContains(response, log_url)

        # view the individual log item
        response = self.client.get(log_url)
        self.assertContains(response, "200")
        self.assertContains(response, "http://org1.bar/zap")
        self.assertNotContains(response, "http://org2.bar/zap")

        # still need to be customer support to do that
        self.login(self.admin)
        response = self.client.get(log_url)
        self.assertLoginRedirect(response)

        # and can't be from other org
        self.login(self.admin2)
        response = self.client.get(log_url)
        self.assertLoginRedirect(response)

        self.login(self.customer_support)

        # can't list logs for deleted ticketer
        list_url = reverse("request_logs.httplog_ticketer", args=[t2.uuid])
        response = self.client.get(list_url)
        self.assertEqual(404, response.status_code)
Ejemplo n.º 9
0
    def test_from_ticket_event(self):
        ticketer = Ticketer.create(self.org, self.user, "mailgun",
                                   "Email ([email protected])", {})
        contact = self.create_contact("Jim", phone="0979111111")
        ticket = self.create_ticket(ticketer,
                                    contact,
                                    "Problem",
                                    body="Where my shoes?")

        # event with a user
        event1 = TicketEvent.objects.create(
            org=self.org,
            contact=contact,
            ticket=ticket,
            event_type=TicketEvent.TYPE_NOTE,
            created_by=self.agent,
            note="this is important",
        )

        self.assertEqual(
            {
                "type": "ticket_note_added",
                "note": "this is important",
                "assignee": None,
                "ticket": {
                    "uuid": str(ticket.uuid),
                    "opened_on": matchers.ISODate(),
                    "closed_on": None,
                    "status": "O",
                    "subject": "Problem",
                    "body": "Where my shoes?",
                    "ticketer": {
                        "uuid": str(ticketer.uuid),
                        "name": "Email ([email protected])"
                    },
                },
                "created_on": matchers.ISODate(),
                "created_by": {
                    "id": self.agent.id,
                    "first_name": "",
                    "last_name": "",
                    "email": "*****@*****.**"
                },
            },
            Event.from_ticket_event(self.org, self.user, event1),
        )

        # event without a user
        event2 = TicketEvent.objects.create(org=self.org,
                                            contact=contact,
                                            ticket=ticket,
                                            event_type=TicketEvent.TYPE_CLOSED)

        self.assertEqual(
            {
                "type": "ticket_closed",
                "note": None,
                "assignee": None,
                "ticket": {
                    "uuid": str(ticket.uuid),
                    "opened_on": matchers.ISODate(),
                    "closed_on": None,
                    "status": "O",
                    "subject": "Problem",
                    "body": "Where my shoes?",
                    "ticketer": {
                        "uuid": str(ticketer.uuid),
                        "name": "Email ([email protected])"
                    },
                },
                "created_on": matchers.ISODate(),
                "created_by": None,
            },
            Event.from_ticket_event(self.org, self.user, event2),
        )