Example #1
0
    def send_sample_sms(self, data):
        request_token = data.get("request_token")
        if not self.get_cached_webhook_secret(request_token):
            return {"success": False, "unexpected_error": self.unexpected_error}

        outgoing_sms_form = TelerivetOutgoingSMSForm(
            {"api_key": data.get("api_key"), "project_id": data.get("project_id"), "phone_id": data.get("phone_id")}
        )

        test_sms_form = TelerivetPhoneNumberForm({"test_phone_number": data.get("test_phone_number")})

        # Be sure to call .is_valid() on both
        outgoing_sms_form_valid = outgoing_sms_form.is_valid()
        test_sms_form_valid = test_sms_form.is_valid()
        if not outgoing_sms_form_valid or not test_sms_form_valid:
            return {
                "success": False,
                "api_key_error": self.get_error_message(outgoing_sms_form, "api_key"),
                "project_id_error": self.get_error_message(outgoing_sms_form, "project_id"),
                "phone_id_error": self.get_error_message(outgoing_sms_form, "phone_id"),
                "test_phone_number_error": self.get_error_message(test_sms_form, "test_phone_number"),
            }

        tmp_backend = SQLTelerivetBackend()
        tmp_backend.set_extra_fields(
            api_key=outgoing_sms_form.cleaned_data.get("api_key"),
            project_id=outgoing_sms_form.cleaned_data.get("project_id"),
            phone_id=outgoing_sms_form.cleaned_data.get("phone_id"),
        )
        sms = SMS(
            phone_number=clean_phone_number(test_sms_form.cleaned_data.get("test_phone_number")),
            text="This is a test SMS from CommCareHQ.",
        )
        tmp_backend.send(sms)
        return {"success": True}
def bootstrap_telerivet_gateway(apps):
    default_currency, _ = (apps.get_model('accounting', 'Currency')
                           if apps else Currency).objects.get_or_create(
                               code=settings.DEFAULT_CURRENCY)
    sms_gateway_fee_class = apps.get_model(
        'smsbillables', 'SmsGatewayFee') if apps else SmsGatewayFee
    sms_gateway_fee_criteria_class = apps.get_model(
        'smsbillables',
        'SmsGatewayFeeCriteria') if apps else SmsGatewayFeeCriteria

    SmsGatewayFee.create_new(
        SQLTelerivetBackend.get_api_id(),
        INCOMING,
        Decimal('0.0'),
        currency=default_currency,
        fee_class=sms_gateway_fee_class,
        criteria_class=sms_gateway_fee_criteria_class,
    )

    SmsGatewayFee.create_new(
        SQLTelerivetBackend.get_api_id(),
        OUTGOING,
        Decimal('0.0'),
        currency=default_currency,
        fee_class=sms_gateway_fee_class,
        criteria_class=sms_gateway_fee_criteria_class,
    )

    log_smsbillables_info("Updated Telerivet gateway fees.")
Example #3
0
def process_incoming_message(*args, **kwargs):
    try:
        from corehq.messaging.smsbackends.telerivet.views import TELERIVET_INBOUND_FIELD_MAP
        fields = {a: kwargs[a] for (a, b) in TELERIVET_INBOUND_FIELD_MAP}
        log = IncomingRequest(**fields)
        log.save()
    except Exception as e:
        notify_exception(None, "Could not save Telerivet log entry")
        pass

    backend = SQLTelerivetBackend.by_webhook_secret(kwargs["secret"])
    if backend is None:
        # Ignore the message if the webhook secret is not recognized
        return

    if kwargs["from_number_e164"]:
        from_number = strip_plus(kwargs["from_number_e164"])
    else:
        from_number = strip_plus(kwargs["from_number"])

    if kwargs["event"] == EVENT_INCOMING:
        if kwargs["message_type"] == MESSAGE_TYPE_SMS:
            domain_scope = backend.domain if not backend.is_global else None
            incoming_sms(from_number, kwargs["content"], SQLTelerivetBackend.get_api_id(),
                domain_scope=domain_scope, backend_id=backend.couch_id)
        elif kwargs["message_type"] == MESSAGE_TYPE_CALL:
            log_call(from_number, "TELERIVET-%s" % kwargs["message_id"], backend=backend)
Example #4
0
class TestProcessMessageStatus(TestCase):
    def setUp(self):
        super(TestProcessMessageStatus, self).setUp()
        self.backend = SQLTelerivetBackend(
            name='TELERIVET',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id())
        self.backend.set_extra_fields(
            webhook_secret='The chamber of webhook secrets')
        self.backend.save()

        self.sms = SMS(
            text='I am testy',
            custom_metadata={'case_id': '123'},
        )
        self.sms.save()

    def tearDown(self):
        self.sms.delete()
        super(TestProcessMessageStatus, self).tearDown()

    def test_status_delivered(self):
        process_message_status(self.sms, DELIVERED)

        sms = SMS.objects.get(couch_id=self.sms.couch_id)
        self.assertTrue('gateway_delivered' in sms.custom_metadata.keys())

    def test_error_status(self):
        message_id = self.sms.couch_id
        process_message_status(self.sms,
                               FAILED,
                               error_message='Somthing went wrong')

        sms = SMS.objects.get(couch_id=message_id)
        self.assertTrue('gateway_delivered' not in sms.custom_metadata.keys())
Example #5
0
def process_incoming_message(*args, **kwargs):
    try:
        from corehq.messaging.smsbackends.telerivet.views import TELERIVET_INBOUND_FIELD_MAP
        fields = {a: kwargs[a] for (a, b) in TELERIVET_INBOUND_FIELD_MAP}
        log = IncomingRequest(**fields)
        log.save()
    except Exception as e:
        notify_exception(None, "Could not save Telerivet log entry")
        pass

    backend = SQLTelerivetBackend.by_webhook_secret(kwargs["secret"])
    if backend is None:
        # Ignore the message if the webhook secret is not recognized
        return

    if kwargs["from_number_e164"]:
        from_number = strip_plus(kwargs["from_number_e164"])
    else:
        from_number = strip_plus(kwargs["from_number"])

    if kwargs["event"] == EVENT_INCOMING:
        if kwargs["message_type"] == MESSAGE_TYPE_SMS:
            domain_scope = backend.domain if not backend.is_global else None
            incoming_sms(from_number,
                         kwargs["content"],
                         SQLTelerivetBackend.get_api_id(),
                         domain_scope=domain_scope,
                         backend_id=backend.couch_id)
        elif kwargs["message_type"] == MESSAGE_TYPE_CALL:
            incoming_ivr(from_number, "TELERIVET-%s" % kwargs["message_id"],
                         None)
Example #6
0
 def setUp(self):
     super(TelerivetLogCallTestCase, self).setUp()
     self.backend = SQLTelerivetBackend(
         name='MOBILE_BACKEND_TELERIVET',
         is_global=True,
         hq_api_id=SQLTelerivetBackend.get_api_id())
     self.backend.set_extra_fields(webhook_secret='abc')
     self.backend.save()
Example #7
0
    def test_webhook_lookup(self):
        self.assertEqual(SQLTelerivetBackend.by_webhook_secret('abc'),
                         self.backend1)

        self.assertEqual(SQLTelerivetBackend.by_webhook_secret('def'),
                         self.backend2)

        self.assertIsNone(SQLTelerivetBackend.by_webhook_secret('ghi'))
Example #8
0
 def setUp(self):
     super(TelerivetLogCallTestCase, self).setUp()
     self.backend = SQLTelerivetBackend(
         name='MOBILE_BACKEND_TELERIVET',
         is_global=True,
         hq_api_id=SQLTelerivetBackend.get_api_id()
     )
     self.backend.set_extra_fields(webhook_secret='abc')
     self.backend.save()
Example #9
0
    def setUp(self):
        self.backend = SQLTelerivetBackend(
            name='TELERIVET',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id())
        self.backend.set_extra_fields(
            webhook_secret='The chamber of webhook secrets')
        self.backend.save()

        self.sms = SMS(phone_number='27845698785', text="Fame is fickle")
        self.sms.save()
    def test_webhook_lookup(self):
        self.assertEqual(
            SQLTelerivetBackend.by_webhook_secret('abc'),
            self.backend1
        )

        self.assertEqual(
            SQLTelerivetBackend.by_webhook_secret('def'),
            self.backend2
        )

        self.assertIsNone(SQLTelerivetBackend.by_webhook_secret('ghi'))
Example #11
0
    def setUp(self):
        super(TestProcessMessageStatus, self).setUp()
        self.backend = SQLTelerivetBackend(
            name='TELERIVET',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id())
        self.backend.set_extra_fields(
            webhook_secret='The chamber of webhook secrets')
        self.backend.save()

        self.sms = SMS(
            text='I am testy',
            custom_metadata={'case_id': '123'},
        )
        self.sms.save()
Example #12
0
def message_status(request, message_id):
    status = request.POST.get('status')
    logger.info(
        f'Updating Telerivet message status: message_id={message_id}, status={status}'
    )

    request_secret = request.POST.get('secret', '')
    backend = None
    if request_secret:
        backend = SQLTelerivetBackend.by_webhook_secret(request_secret)

    if backend is None:
        return HttpResponseForbidden('Invalid secret')

    try:
        sms = SMS.objects.get(couch_id=message_id)
    except SMS.DoesNotExist:
        raise Http404()
    else:
        process_message_status(
            sms,
            status,
            error_message=request.POST.get('error_message', ''),
        )
        return HttpResponse()
Example #13
0
    def __init__(self, is_superuser=False, *args, **kwargs):
        super(InitiateAddSMSBackendForm, self).__init__(*args, **kwargs)

        from corehq.messaging.smsbackends.telerivet.models import SQLTelerivetBackend
        backend_classes = get_sms_backend_classes()
        backend_choices = []
        for api_id, klass in backend_classes.items():
            if is_superuser or api_id == SQLTelerivetBackend.get_api_id():
                friendly_name = klass.get_generic_name()
                backend_choices.append((api_id, friendly_name))
        backend_choices = sorted(backend_choices,
                                 key=lambda backend: backend[1])
        self.fields['hq_api_id'].choices = backend_choices

        self.helper = HQFormHelper()
        self.helper.layout = crispy.Layout(
            hqcrispy.B3MultiField(
                _("Create Another Gateway"),
                InlineField('action'),
                Div(InlineField('hq_api_id', css_class="ko-select2"),
                    css_class='col-sm-6 col-md-6 col-lg-4'),
                Div(StrictButton(mark_safe(
                    '<i class="fa fa-plus"></i> Add Another Gateway'),
                                 css_class='btn-primary',
                                 type='submit',
                                 style="margin-left:5px;"),
                    css_class='col-sm-3 col-md-2 col-lg-2'),
            ), )
Example #14
0
    def __init__(self, is_superuser=False, *args, **kwargs):
        super(InitiateAddSMSBackendForm, self).__init__(*args, **kwargs)

        from corehq.messaging.smsbackends.telerivet.models import SQLTelerivetBackend
        backend_classes = get_sms_backend_classes()
        backend_choices = []
        for api_id, klass in backend_classes.items():
            if is_superuser or api_id == SQLTelerivetBackend.get_api_id():
                friendly_name = klass.get_generic_name()
                backend_choices.append((api_id, friendly_name))
        self.fields['hq_api_id'].choices = backend_choices

        self.helper = FormHelper()
        self.helper.label_class = 'col-sm-3 col-md-4 col-lg-2'
        self.helper.field_class = 'col-sm-9 col-md-8 col-lg-6'
        self.helper.form_class = "form form-horizontal"
        self.helper.layout = crispy.Layout(
            hqcrispy.B3MultiField(
                _("Create Another Gateway"),
                InlineField('action'),
                Div(InlineField('hq_api_id'), css_class='col-sm-6 col-md-6 col-lg-4'),
                Div(StrictButton(
                    mark_safe('<i class="fa fa-plus"></i> Add Another Gateway'),
                    css_class='btn-success',
                    type='submit',
                    style="margin-left:5px;"
                ), css_class='col-sm-3 col-md-2 col-lg-2'),
            ),
        )
Example #15
0
 def clean_webhook_secret(self):
     # Circular import
     from corehq.messaging.smsbackends.telerivet.models import SQLTelerivetBackend
     value = self.cleaned_data['webhook_secret']
     backend = SQLTelerivetBackend.by_webhook_secret(value)
     if backend and backend.pk != self._cchq_backend_id:
         raise ValidationError(_("Already in use."))
     return value
Example #16
0
 def clean_webhook_secret(self):
     # Circular import
     from corehq.messaging.smsbackends.telerivet.models import SQLTelerivetBackend
     value = self.cleaned_data['webhook_secret']
     backend = SQLTelerivetBackend.by_webhook_secret(value)
     if backend and backend.pk != self._cchq_backend_id:
         raise ValidationError(_("Already in use."))
     return value
Example #17
0
def send_sample_sms(request, domain):
    request_token = request.POST.get('request_token')
    if not TelerivetSetupView.get_cached_webhook_secret(request_token):
        return {
            'success': False,
            'unexpected_error': TelerivetSetupView.unexpected_error,
        }

    outgoing_sms_form = TelerivetOutgoingSMSForm({
        'api_key': request.POST.get('api_key'),
        'project_id': request.POST.get('project_id'),
        'phone_id': request.POST.get('phone_id'),
    })

    test_sms_form = TelerivetPhoneNumberForm({
        'test_phone_number': request.POST.get('test_phone_number'),
    })

    # Be sure to call .is_valid() on both
    outgoing_sms_form_valid = outgoing_sms_form.is_valid()
    test_sms_form_valid = test_sms_form.is_valid()
    if not outgoing_sms_form_valid or not test_sms_form_valid:
        return json_response({
            'success': False,
            'api_key_error': TelerivetSetupView.get_error_message(outgoing_sms_form, 'api_key'),
            'project_id_error': TelerivetSetupView.get_error_message(outgoing_sms_form, 'project_id'),
            'phone_id_error': TelerivetSetupView.get_error_message(outgoing_sms_form, 'phone_id'),
            'test_phone_number_error': TelerivetSetupView.get_error_message(test_sms_form, 'test_phone_number'),
        })

    tmp_backend = SQLTelerivetBackend()
    tmp_backend.set_extra_fields(
        api_key=outgoing_sms_form.cleaned_data.get('api_key'),
        project_id=outgoing_sms_form.cleaned_data.get('project_id'),
        phone_id=outgoing_sms_form.cleaned_data.get('phone_id'),
    )
    sms = SMS(
        phone_number=clean_phone_number(test_sms_form.cleaned_data.get('test_phone_number')),
        text="This is a test SMS from CommCareHQ."
    )
    tmp_backend.send(sms)
    return json_response({
        'success': True,
    })
Example #18
0
def create_backend(request, domain):
    webhook_secret = TelerivetSetupView.get_cached_webhook_secret(
        request.POST.get('request_token'))
    values = {
        'name': request.POST.get('name'),
        'description': _("My Telerivet Gateway"),
        'api_key': request.POST.get('api_key'),
        'project_id': request.POST.get('project_id'),
        'phone_id': request.POST.get('phone_id'),
        'webhook_secret': webhook_secret,
    }
    form = TelerivetBackendForm(values, domain=domain, backend_id=None)
    if form.is_valid():
        with transaction.atomic():
            backend = SQLTelerivetBackend(
                backend_type=SQLMobileBackend.SMS,
                inbound_api_key=webhook_secret,
                hq_api_id=SQLTelerivetBackend.get_api_id(),
                is_global=False,
                domain=domain,
                name=form.cleaned_data.get('name'),
                description=form.cleaned_data.get('description'))
            backend.set_extra_fields(
                api_key=form.cleaned_data.get('api_key'),
                project_id=form.cleaned_data.get('project_id'),
                phone_id=form.cleaned_data.get('phone_id'),
                webhook_secret=webhook_secret)
            phone_number = backend.get_phone_number_or_none()
            if phone_number:
                backend.description += ' {}'.format(phone_number)
                backend.reply_to_phone_number = phone_number
            backend.save()
            if request.POST.get(
                    'set_as_default') == FinalizeGatewaySetupForm.YES:
                SQLMobileBackendMapping.set_default_domain_backend(
                    domain, backend)
            return json_response({'success': True})

    name_error = TelerivetSetupView.get_error_message(form, 'name')
    return json_response({
        'success':
        False,
        'name_error':
        name_error,
        'unexpected_error':
        None if name_error else TelerivetSetupView.unexpected_error,
    })
    def setUp(self):
        self.backend1 = SQLTelerivetBackend(
            name='TELERIVET1',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id()
        )
        self.backend1.set_extra_fields(
            webhook_secret='abc'
        )
        self.backend1.save()

        self.backend2 = SQLTelerivetBackend(
            name='TELERIVET2',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id()
        )
        self.backend2.set_extra_fields(
            webhook_secret='def'
        )
        self.backend2.save()
Example #20
0
class TelerivetLogCallTestCase(util.LogCallTestCase):
    def setUp(self):
        super(TelerivetLogCallTestCase, self).setUp()
        self.backend = SQLTelerivetBackend(
            name='MOBILE_BACKEND_TELERIVET',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id())
        self.backend.set_extra_fields(webhook_secret='abc')
        self.backend.save()

    def tearDown(self):
        self.backend.delete()
        super(TelerivetLogCallTestCase, self).tearDown()

    def simulate_inbound_call(self, phone_number):
        return Client().post(
            '/telerivet/in/', {
                'secret': 'abc',
                'from_number_e164': phone_number,
                'event': EVENT_INCOMING,
                'message_type': MESSAGE_TYPE_CALL,
                'id': 'xyz',
            })

    def check_response(self, response):
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content.decode('utf-8'), '')
Example #21
0
class TelerivetLogCallTestCase(util.LogCallTestCase):

    def setUp(self):
        super(TelerivetLogCallTestCase, self).setUp()
        self.backend = SQLTelerivetBackend(
            name='MOBILE_BACKEND_TELERIVET',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id()
        )
        self.backend.set_extra_fields(webhook_secret='abc')
        self.backend.save()

    def tearDown(self):
        self.backend.delete()
        super(TelerivetLogCallTestCase, self).tearDown()

    def simulate_inbound_call(self, phone_number):
        return Client().post('/telerivet/in/', {
            'secret': 'abc',
            'from_number_e164': phone_number,
            'event': EVENT_INCOMING,
            'message_type': MESSAGE_TYPE_CALL,
            'id': 'xyz',
        })

    def check_response(self, response):
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, '')
Example #22
0
 def setUp(self):
     self.client = Client()
     self.twilio_url = reverse(AddDomainGatewayView.urlname,
                               kwargs={
                                   'domain': DOMAIN_NAME,
                                   'hq_api_id':
                                   SQLTwilioBackend.get_api_id()
                               })
     self.telerivet_url = reverse(AddDomainGatewayView.urlname,
                                  kwargs={
                                      'domain':
                                      DOMAIN_NAME,
                                      'hq_api_id':
                                      SQLTelerivetBackend.get_api_id()
                                  })
Example #23
0
def bootstrap_telerivet_gateway(apps):
    default_currency, _  = (apps.get_model('accounting', 'Currency') if apps else Currency).objects.get_or_create(code=settings.DEFAULT_CURRENCY)
    sms_gateway_fee_class = apps.get_model('smsbillables', 'SmsGatewayFee') if apps else SmsGatewayFee
    sms_gateway_fee_criteria_class = apps.get_model('smsbillables', 'SmsGatewayFeeCriteria') if apps else SmsGatewayFeeCriteria

    SmsGatewayFee.create_new(
        SQLTelerivetBackend.get_api_id(),
        INCOMING,
        Decimal('0.0'),
        currency=default_currency,
        fee_class=sms_gateway_fee_class,
        criteria_class=sms_gateway_fee_criteria_class,
    )

    SmsGatewayFee.create_new(
        SQLTelerivetBackend.get_api_id(),
        OUTGOING,
        Decimal('0.0'),
        currency=default_currency,
        fee_class=sms_gateway_fee_class,
        criteria_class=sms_gateway_fee_criteria_class,
    )

    log_smsbillables_info("Updated Telerivet gateway fees.")
Example #24
0
def send_sample_sms(request, domain):
    request_token = request.POST.get('request_token')
    if not TelerivetSetupView.get_cached_webhook_secret(request_token):
        return {
            'success': False,
            'unexpected_error': TelerivetSetupView.unexpected_error,
        }

    outgoing_sms_form = TelerivetOutgoingSMSForm({
        'api_key':
        request.POST.get('api_key'),
        'project_id':
        request.POST.get('project_id'),
        'phone_id':
        request.POST.get('phone_id'),
    })

    test_sms_form = TelerivetPhoneNumberForm({
        'test_phone_number':
        request.POST.get('test_phone_number'),
    })

    # Be sure to call .is_valid() on both
    outgoing_sms_form_valid = outgoing_sms_form.is_valid()
    test_sms_form_valid = test_sms_form.is_valid()
    if not outgoing_sms_form_valid or not test_sms_form_valid:
        return json_response({
            'success':
            False,
            'api_key_error':
            TelerivetSetupView.get_error_message(outgoing_sms_form, 'api_key'),
            'project_id_error':
            TelerivetSetupView.get_error_message(outgoing_sms_form,
                                                 'project_id'),
            'phone_id_error':
            TelerivetSetupView.get_error_message(outgoing_sms_form,
                                                 'phone_id'),
            'test_phone_number_error':
            TelerivetSetupView.get_error_message(test_sms_form,
                                                 'test_phone_number'),
        })

    tmp_backend = SQLTelerivetBackend()
    tmp_backend.set_extra_fields(
        api_key=outgoing_sms_form.cleaned_data.get('api_key'),
        project_id=outgoing_sms_form.cleaned_data.get('project_id'),
        phone_id=outgoing_sms_form.cleaned_data.get('phone_id'),
    )
    sms = SMS(phone_number=clean_phone_number(
        test_sms_form.cleaned_data.get('test_phone_number')),
              text="This is a test SMS from CommCareHQ.")
    tmp_backend.send(sms)
    return json_response({
        'success': True,
    })
Example #25
0
    def create_backend(self, data):
        webhook_secret = self.get_cached_webhook_secret(data.get("request_token"))
        values = {
            "name": data.get("name"),
            "description": _("My Telerivet Gateway"),
            "api_key": data.get("api_key"),
            "project_id": data.get("project_id"),
            "phone_id": data.get("phone_id"),
            "webhook_secret": webhook_secret,
        }
        form = TelerivetBackendForm(values, domain=self.domain, backend_id=None)
        if form.is_valid():
            with transaction.atomic():
                backend = SQLTelerivetBackend(
                    backend_type=SQLMobileBackend.SMS,
                    inbound_api_key=webhook_secret,
                    hq_api_id=SQLTelerivetBackend.get_api_id(),
                    is_global=False,
                    domain=self.domain,
                    name=form.cleaned_data.get("name"),
                    description=form.cleaned_data.get("description"),
                )
                backend.set_extra_fields(
                    api_key=form.cleaned_data.get("api_key"),
                    project_id=form.cleaned_data.get("project_id"),
                    phone_id=form.cleaned_data.get("phone_id"),
                    webhook_secret=webhook_secret,
                )
                phone_number = backend.get_phone_number_or_none()
                if phone_number:
                    backend.description += " {}".format(phone_number)
                    backend.reply_to_phone_number = phone_number
                backend.save()
                if data.get("set_as_default") == FinalizeGatewaySetupForm.YES:
                    SQLMobileBackendMapping.set_default_domain_backend(self.domain, backend)
                return {"success": True}

        name_error = self.get_error_message(form, "name")
        return {
            "success": False,
            "name_error": name_error,
            "unexpected_error": None if name_error else self.unexpected_error,
        }
Example #26
0
def create_backend(request, domain):
    webhook_secret = TelerivetSetupView.get_cached_webhook_secret(request.POST.get('request_token'))
    values = {
        'name': request.POST.get('name'),
        'description': _("My Telerivet Gateway"),
        'api_key': request.POST.get('api_key'),
        'project_id': request.POST.get('project_id'),
        'phone_id': request.POST.get('phone_id'),
        'webhook_secret': webhook_secret,
    }
    form = TelerivetBackendForm(values, domain=domain, backend_id=None)
    if form.is_valid():
        with transaction.atomic():
            backend = SQLTelerivetBackend(
                backend_type=SQLMobileBackend.SMS,
                inbound_api_key=webhook_secret,
                hq_api_id=SQLTelerivetBackend.get_api_id(),
                is_global=False,
                domain=domain,
                name=form.cleaned_data.get('name'),
                description=form.cleaned_data.get('description')
            )
            backend.set_extra_fields(
                api_key=form.cleaned_data.get('api_key'),
                project_id=form.cleaned_data.get('project_id'),
                phone_id=form.cleaned_data.get('phone_id'),
                webhook_secret=webhook_secret
            )
            phone_number = backend.get_phone_number_or_none()
            if phone_number:
                backend.description += ' {}'.format(phone_number)
                backend.reply_to_phone_number = phone_number
            backend.save()
            if request.POST.get('set_as_default') == FinalizeGatewaySetupForm.YES:
                SQLMobileBackendMapping.set_default_domain_backend(domain, backend)
            return json_response({'success': True})

    name_error = TelerivetSetupView.get_error_message(form, 'name')
    return json_response({
        'success': False,
        'name_error': name_error,
        'unexpected_error': None if name_error else TelerivetSetupView.unexpected_error,
    })
Example #27
0
    def setUp(self):
        self.backend1 = SQLTelerivetBackend(
            name='TELERIVET1',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id())
        self.backend1.set_extra_fields(webhook_secret='abc')
        self.backend1.save()

        self.backend2 = SQLTelerivetBackend(
            name='TELERIVET2',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id())
        self.backend2.set_extra_fields(webhook_secret='def')
        self.backend2.save()
Example #28
0
    def create_backend(self, data):
        webhook_secret = self.get_cached_webhook_secret(data.get('request_token'))
        values = {
            'name': data.get('name'),
            'description': _("My Telerivet Gateway '{}'").format(data.get('name')),
            'api_key': data.get('api_key'),
            'project_id': data.get('project_id'),
            'phone_id': data.get('phone_id'),
            'webhook_secret': webhook_secret,
        }
        form = TelerivetBackendForm(values, domain=self.domain, backend_id=None)
        if form.is_valid():
            with transaction.atomic():
                backend = SQLTelerivetBackend(
                    backend_type=SQLMobileBackend.SMS,
                    inbound_api_key=webhook_secret,
                    hq_api_id=SQLTelerivetBackend.get_api_id(),
                    is_global=False,
                    domain=self.domain,
                    name=form.cleaned_data.get('name'),
                    description=form.cleaned_data.get('description')
                )
                backend.set_extra_fields(
                    api_key=form.cleaned_data.get('api_key'),
                    project_id=form.cleaned_data.get('project_id'),
                    phone_id=form.cleaned_data.get('phone_id'),
                    webhook_secret=webhook_secret
                )
                backend.save()
                if data.get('set_as_default') == FinalizeGatewaySetupForm.YES:
                    SQLMobileBackendMapping.set_default_domain_backend(self.domain, backend)
                return {'success': True}

        name_error = self.get_error_message(form, 'name')
        return {
            'success': False,
            'name_error': name_error,
            'unexpected_error': None if name_error else self.unexpected_error,
        }
Example #29
0
class AllBackendTest(BaseSMSTest):
    def setUp(self):
        super(AllBackendTest, self).setUp()

        self.domain_obj = Domain(name='all-backend-test')
        self.domain_obj.save()
        self.create_account_and_subscription(self.domain_obj.name)
        self.domain_obj = Domain.get(self.domain_obj._id)

        self.test_phone_number = '99912345'
        self.contact1 = CommCareCase(domain=self.domain_obj.name)
        self.contact1.set_case_property('contact_phone_number', self.test_phone_number)
        self.contact1.set_case_property('contact_phone_number_is_verified', '1')
        self.contact1.save()
        self.contact1 = CommConnectCase.wrap(self.contact1.to_json())

        # For use with megamobile only
        self.contact2 = CommCareCase(domain=self.domain_obj.name)
        self.contact2.set_case_property('contact_phone_number', '63%s' % self.test_phone_number)
        self.contact2.set_case_property('contact_phone_number_is_verified', '1')
        self.contact2.save()
        self.contact2 = CommConnectCase.wrap(self.contact2.to_json())

        self.unicel_backend = SQLUnicelBackend(
            name='UNICEL',
            is_global=True,
            hq_api_id=SQLUnicelBackend.get_api_id()
        )
        self.unicel_backend.save()

        self.mach_backend = SQLMachBackend(
            name='MACH',
            is_global=True,
            hq_api_id=SQLMachBackend.get_api_id()
        )
        self.mach_backend.save()

        self.tropo_backend = SQLTropoBackend(
            name='TROPO',
            is_global=True,
            hq_api_id=SQLTropoBackend.get_api_id()
        )
        self.tropo_backend.save()

        self.http_backend = SQLHttpBackend(
            name='HTTP',
            is_global=True,
            hq_api_id=SQLHttpBackend.get_api_id()
        )
        self.http_backend.save()

        self.telerivet_backend = SQLTelerivetBackend(
            name='TELERIVET',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id()
        )
        self.telerivet_backend.set_extra_fields(
            **dict(
                webhook_secret='telerivet-webhook-secret'
            )
        )
        self.telerivet_backend.save()

        self.test_backend = SQLTestSMSBackend(
            name='TEST',
            is_global=True,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )
        self.test_backend.save()

        self.grapevine_backend = SQLGrapevineBackend(
            name='GRAPEVINE',
            is_global=True,
            hq_api_id=SQLGrapevineBackend.get_api_id()
        )
        self.grapevine_backend.save()

        self.twilio_backend = SQLTwilioBackend(
            name='TWILIO',
            is_global=True,
            hq_api_id=SQLTwilioBackend.get_api_id()
        )
        self.twilio_backend.save()

        self.megamobile_backend = SQLMegamobileBackend(
            name='MEGAMOBILE',
            is_global=True,
            hq_api_id=SQLMegamobileBackend.get_api_id()
        )
        self.megamobile_backend.save()

        self.smsgh_backend = SQLSMSGHBackend(
            name='SMSGH',
            is_global=True,
            hq_api_id=SQLSMSGHBackend.get_api_id()
        )
        self.smsgh_backend.save()

        self.apposit_backend = SQLAppositBackend(
            name='APPOSIT',
            is_global=True,
            hq_api_id=SQLAppositBackend.get_api_id()
        )
        self.apposit_backend.save()

        self.sislog_backend = SQLSislogBackend(
            name='SISLOG',
            is_global=True,
            hq_api_id=SQLSislogBackend.get_api_id()
        )
        self.sislog_backend.save()

        self.yo_backend = SQLYoBackend(
            name='YO',
            is_global=True,
            hq_api_id=SQLYoBackend.get_api_id()
        )
        self.yo_backend.save()

    def _test_outbound_backend(self, backend, msg_text, mock_send):
        SQLMobileBackendMapping.set_default_domain_backend(self.domain_obj.name, backend)

        send_sms(self.domain_obj.name, None, self.test_phone_number, msg_text)
        sms = SMS.objects.get(
            domain=self.domain_obj.name,
            direction='O',
            text=msg_text
        )

        self.assertTrue(mock_send.called)
        msg_arg = mock_send.call_args[0][0]
        self.assertEqual(msg_arg.date, sms.date)
        self.assertEqual(sms.backend_api, backend.hq_api_id)
        self.assertEqual(sms.backend_id, backend.couch_id)

    def _verify_inbound_request(self, backend_api_id, msg_text, backend_couch_id=None):
        sms = SMS.objects.get(
            domain=self.domain_obj.name,
            direction='I',
            text=msg_text
        )
        self.assertEqual(sms.backend_api, backend_api_id)
        if backend_couch_id:
            self.assertEqual(sms.backend_id, backend_couch_id)

    def _simulate_inbound_request_with_payload(self, url,
            content_type, payload):
        response = Client().post(url, payload, content_type=content_type)
        self.assertEqual(response.status_code, 200)

    def _simulate_inbound_request(self, url, phone_param,
            msg_param, msg_text, post=False, additional_params=None,
            expected_response_code=200):
        fcn = Client().post if post else Client().get

        payload = {
            phone_param: self.test_phone_number,
            msg_param: msg_text,
        }

        if additional_params:
            payload.update(additional_params)

        response = fcn(url, payload)
        self.assertEqual(response.status_code, expected_response_code)

    @patch('corehq.messaging.smsbackends.unicel.models.SQLUnicelBackend.send')
    @patch('corehq.messaging.smsbackends.mach.models.SQLMachBackend.send')
    @patch('corehq.messaging.smsbackends.tropo.models.SQLTropoBackend.send')
    @patch('corehq.messaging.smsbackends.http.models.SQLHttpBackend.send')
    @patch('corehq.messaging.smsbackends.telerivet.models.SQLTelerivetBackend.send')
    @patch('corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send')
    @patch('corehq.messaging.smsbackends.grapevine.models.SQLGrapevineBackend.send')
    @patch('corehq.messaging.smsbackends.twilio.models.SQLTwilioBackend.send')
    @patch('corehq.messaging.smsbackends.megamobile.models.SQLMegamobileBackend.send')
    @patch('corehq.messaging.smsbackends.smsgh.models.SQLSMSGHBackend.send')
    @patch('corehq.messaging.smsbackends.apposit.models.SQLAppositBackend.send')
    @patch('corehq.messaging.smsbackends.sislog.models.SQLSislogBackend.send')
    @patch('corehq.messaging.smsbackends.yo.models.SQLYoBackend.send')
    def test_outbound_sms(
            self,
            yo_send,
            sislog_send,
            apposit_send,
            smsgh_send,
            megamobile_send,
            twilio_send,
            grapevine_send,
            test_send,
            telerivet_send,
            http_send,
            tropo_send,
            mach_send,
            unicel_send):
        self._test_outbound_backend(self.unicel_backend, 'unicel test', unicel_send)
        self._test_outbound_backend(self.mach_backend, 'mach test', mach_send)
        self._test_outbound_backend(self.tropo_backend, 'tropo test', tropo_send)
        self._test_outbound_backend(self.http_backend, 'http test', http_send)
        self._test_outbound_backend(self.telerivet_backend, 'telerivet test', telerivet_send)
        self._test_outbound_backend(self.test_backend, 'test test', test_send)
        self._test_outbound_backend(self.grapevine_backend, 'grapevine test', grapevine_send)
        self._test_outbound_backend(self.twilio_backend, 'twilio test', twilio_send)
        self._test_outbound_backend(self.megamobile_backend, 'megamobile test', megamobile_send)
        self._test_outbound_backend(self.smsgh_backend, 'smsgh test', smsgh_send)
        self._test_outbound_backend(self.apposit_backend, 'apposit test', apposit_send)
        self._test_outbound_backend(self.sislog_backend, 'sislog test', sislog_send)
        self._test_outbound_backend(self.yo_backend, 'yo test', yo_send)

    def test_unicel_inbound_sms(self):
        self._simulate_inbound_request('/unicel/in/', phone_param=InboundParams.SENDER,
            msg_param=InboundParams.MESSAGE, msg_text='unicel test')

        self._verify_inbound_request(self.unicel_backend.get_api_id(), 'unicel test')

    def test_tropo_inbound_sms(self):
        tropo_data = {'session': {'from': {'id': self.test_phone_number}, 'initialText': 'tropo test'}}
        self._simulate_inbound_request_with_payload('/tropo/sms/',
            content_type='text/json', payload=json.dumps(tropo_data))

        self._verify_inbound_request(self.tropo_backend.get_api_id(), 'tropo test')

    def test_telerivet_inbound_sms(self):
        additional_params = {
            'event': 'incoming_message',
            'message_type': 'sms',
            'secret': self.telerivet_backend.config.webhook_secret
        }
        self._simulate_inbound_request('/telerivet/in/', phone_param='from_number_e164',
            msg_param='content', msg_text='telerivet test', post=True,
            additional_params=additional_params)

        self._verify_inbound_request(self.telerivet_backend.get_api_id(), 'telerivet test')

    @override_settings(SIMPLE_API_KEYS={'grapevine-test': 'grapevine-api-key'})
    def test_grapevine_inbound_sms(self):
        xml = """
        <gviSms>
            <smsDateTime>2015-10-12T12:00:00</smsDateTime>
            <cellNumber>99912345</cellNumber>
            <content>grapevine test</content>
        </gviSms>
        """
        payload = urlencode({'XML': xml})
        self._simulate_inbound_request_with_payload(
            '/gvi/api/sms/?apiuser=grapevine-test&apikey=grapevine-api-key',
            content_type='application/x-www-form-urlencoded', payload=payload)

        self._verify_inbound_request(self.grapevine_backend.get_api_id(), 'grapevine test')

    def test_twilio_inbound_sms(self):
        url = '/twilio/sms/%s' % self.twilio_backend.inbound_api_key
        self._simulate_inbound_request(url, phone_param='From',
            msg_param='Body', msg_text='twilio test', post=True)

        self._verify_inbound_request(self.twilio_backend.get_api_id(), 'twilio test',
            backend_couch_id=self.twilio_backend.couch_id)

    def test_twilio_401_response(self):
        start_count = SMS.objects.count()

        self._simulate_inbound_request('/twilio/sms/xxxxx', phone_param='From',
            msg_param='Body', msg_text='twilio test', post=True,
            expected_response_code=401)

        end_count = SMS.objects.count()

        self.assertEqual(start_count, end_count)

    def test_megamobile_inbound_sms(self):
        self._simulate_inbound_request('/megamobile/sms/', phone_param='cel',
            msg_param='msg', msg_text='megamobile test')

        self._verify_inbound_request(self.megamobile_backend.get_api_id(), 'megamobile test')

    def test_sislog_inbound_sms(self):
        self._simulate_inbound_request('/sislog/in/', phone_param='sender',
            msg_param='msgdata', msg_text='sislog test')

        self._verify_inbound_request(self.sislog_backend.get_api_id(), 'sislog test')

    def test_yo_inbound_sms(self):
        self._simulate_inbound_request('/yo/sms/', phone_param='sender',
            msg_param='message', msg_text='yo test')

        self._verify_inbound_request(self.yo_backend.get_api_id(), 'yo test')

    def test_smsgh_inbound_sms(self):
        user = ApiUser.create('smsgh-api-key', 'smsgh-api-key', permissions=[PERMISSION_POST_SMS])
        user.save()

        self._simulate_inbound_request('/smsgh/sms/smsgh-api-key/', phone_param='snr',
            msg_param='msg', msg_text='smsgh test')

        self._verify_inbound_request('SMSGH', 'smsgh test')

        user.delete()

    def test_apposit_inbound_sms(self):
        user = ApiUser.create('apposit-api-key', 'apposit-api-key', permissions=[PERMISSION_POST_SMS])
        user.save()

        self._simulate_inbound_request(
            '/apposit/in/apposit-api-key/',
            phone_param='fromAddress',
            msg_param='content',
            msg_text='apposit test',
            post=True,
            additional_params={'channel': 'SMS'}
        )
        self._verify_inbound_request('APPOSIT', 'apposit test')

        user.delete()

    def tearDown(self):
        delete_domain_phone_numbers(self.domain_obj.name)
        self.contact1.delete()
        self.contact2.delete()
        self.domain_obj.delete()
        self.unicel_backend.delete()
        self.mach_backend.delete()
        self.tropo_backend.delete()
        self.http_backend.delete()
        self.telerivet_backend.delete()
        self.test_backend.delete()
        self.grapevine_backend.delete()
        self.twilio_backend.delete()
        self.megamobile_backend.delete()
        self.smsgh_backend.delete()
        self.apposit_backend.delete()
        self.sislog_backend.delete()
        self.yo_backend.delete()
        super(AllBackendTest, self).tearDown()
Example #30
0
class TelerivetViewTestCase(TestCase):

    view_path = 'telerivet_message_status'

    def setUp(self):
        self.backend = SQLTelerivetBackend(
            name='TELERIVET',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id())
        self.backend.set_extra_fields(
            webhook_secret='The chamber of webhook secrets')
        self.backend.save()

        self.sms = SMS(phone_number='27845698785', text="Fame is fickle")
        self.sms.save()

    def tearDown(self):
        self.backend.delete()
        self.sms.delete()

    def test_message_status_successful_without_prior_metadata(self):
        data = {
            'status': 'delivered',
            'secret': self.backend.config.webhook_secret
        }
        response = self.client.post(
            reverse(self.view_path, kwargs={'message_id': self.sms.couch_id}),
            data)

        self.assertTrue(response.status_code, 200)
        self.sms.refresh_from_db()

        expected_custom_metadata = {'gateway_delivered': True}
        self.assertEqual(self.sms.custom_metadata, expected_custom_metadata)

    def test_message_status_successful_with_metadata(self):
        self.sms.custom_metadata = {'custom': 'data'}
        self.sms.save()

        data = {
            'status': 'delivered',
            'secret': self.backend.config.webhook_secret
        }
        response = self.client.post(
            reverse(self.view_path, kwargs={'message_id': self.sms.couch_id}),
            data)

        self.assertTrue(response.status_code, 200)
        self.sms.refresh_from_db()

        expected_custom_metadata = {
            'custom': 'data',
            'gateway_delivered': True
        }
        self.assertEqual(self.sms.custom_metadata, expected_custom_metadata)

    def test_message_status_with_wrong_message_id(self):
        self.sms.custom_metadata = {}
        self.sms.save()

        data = {
            'status': 'delivered',
            'secret': self.backend.config.webhook_secret
        }
        response = self.client.post(
            reverse(self.view_path,
                    kwargs={'message_id': f'{self.sms.couch_id}123'}), data)

        self.assertTrue(response.status_code == 404)

    def test_message_status_with_invalid_secret(self):
        self.sms.custom_metadata = {}
        self.sms.save()

        data = {'status': 'delivered', 'secret': 'not a secret'}
        response = self.client.post(
            reverse(self.view_path, kwargs={'message_id': self.sms.couch_id}),
            data)

        self.assertTrue(response.status_code == 403)
Example #31
0
    def setUp(self):
        super(AllBackendTest, self).setUp()

        self.domain_obj = Domain(name='all-backend-test')
        self.domain_obj.save()
        self.create_account_and_subscription(self.domain_obj.name)
        self.domain_obj = Domain.get(self.domain_obj._id)

        self.test_phone_number = '99912345'
        self.contact1 = CommCareCase(domain=self.domain_obj.name)
        self.contact1.set_case_property('contact_phone_number', self.test_phone_number)
        self.contact1.set_case_property('contact_phone_number_is_verified', '1')
        self.contact1.save()
        self.contact1 = CommConnectCase.wrap(self.contact1.to_json())

        # For use with megamobile only
        self.contact2 = CommCareCase(domain=self.domain_obj.name)
        self.contact2.set_case_property('contact_phone_number', '63%s' % self.test_phone_number)
        self.contact2.set_case_property('contact_phone_number_is_verified', '1')
        self.contact2.save()
        self.contact2 = CommConnectCase.wrap(self.contact2.to_json())

        self.unicel_backend = SQLUnicelBackend(
            name='UNICEL',
            is_global=True,
            hq_api_id=SQLUnicelBackend.get_api_id()
        )
        self.unicel_backend.save()

        self.mach_backend = SQLMachBackend(
            name='MACH',
            is_global=True,
            hq_api_id=SQLMachBackend.get_api_id()
        )
        self.mach_backend.save()

        self.tropo_backend = SQLTropoBackend(
            name='TROPO',
            is_global=True,
            hq_api_id=SQLTropoBackend.get_api_id()
        )
        self.tropo_backend.save()

        self.http_backend = SQLHttpBackend(
            name='HTTP',
            is_global=True,
            hq_api_id=SQLHttpBackend.get_api_id()
        )
        self.http_backend.save()

        self.telerivet_backend = SQLTelerivetBackend(
            name='TELERIVET',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id()
        )
        self.telerivet_backend.set_extra_fields(
            **dict(
                webhook_secret='telerivet-webhook-secret'
            )
        )
        self.telerivet_backend.save()

        self.test_backend = SQLTestSMSBackend(
            name='TEST',
            is_global=True,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )
        self.test_backend.save()

        self.grapevine_backend = SQLGrapevineBackend(
            name='GRAPEVINE',
            is_global=True,
            hq_api_id=SQLGrapevineBackend.get_api_id()
        )
        self.grapevine_backend.save()

        self.twilio_backend = SQLTwilioBackend(
            name='TWILIO',
            is_global=True,
            hq_api_id=SQLTwilioBackend.get_api_id()
        )
        self.twilio_backend.save()

        self.megamobile_backend = SQLMegamobileBackend(
            name='MEGAMOBILE',
            is_global=True,
            hq_api_id=SQLMegamobileBackend.get_api_id()
        )
        self.megamobile_backend.save()

        self.smsgh_backend = SQLSMSGHBackend(
            name='SMSGH',
            is_global=True,
            hq_api_id=SQLSMSGHBackend.get_api_id()
        )
        self.smsgh_backend.save()

        self.apposit_backend = SQLAppositBackend(
            name='APPOSIT',
            is_global=True,
            hq_api_id=SQLAppositBackend.get_api_id()
        )
        self.apposit_backend.save()

        self.sislog_backend = SQLSislogBackend(
            name='SISLOG',
            is_global=True,
            hq_api_id=SQLSislogBackend.get_api_id()
        )
        self.sislog_backend.save()

        self.yo_backend = SQLYoBackend(
            name='YO',
            is_global=True,
            hq_api_id=SQLYoBackend.get_api_id()
        )
        self.yo_backend.save()
Example #32
0
class TelerivetWebhookLookupTestCase(TestCase):
    def setUp(self):
        self.backend1 = SQLTelerivetBackend(
            name='TELERIVET1',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id())
        self.backend1.set_extra_fields(webhook_secret='abc')
        self.backend1.save()

        self.backend2 = SQLTelerivetBackend(
            name='TELERIVET2',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id())
        self.backend2.set_extra_fields(webhook_secret='def')
        self.backend2.save()

    def tearDown(self):
        self.backend1.delete()
        self.backend2.delete()

    def test_webhook_lookup(self):
        self.assertEqual(SQLTelerivetBackend.by_webhook_secret('abc'),
                         self.backend1)

        self.assertEqual(SQLTelerivetBackend.by_webhook_secret('def'),
                         self.backend2)

        self.assertIsNone(SQLTelerivetBackend.by_webhook_secret('ghi'))
class TelerivetWebhookLookupTestCase(TestCase):
    def setUp(self):
        self.backend1 = SQLTelerivetBackend(
            name='TELERIVET1',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id()
        )
        self.backend1.set_extra_fields(
            webhook_secret='abc'
        )
        self.backend1.save()

        self.backend2 = SQLTelerivetBackend(
            name='TELERIVET2',
            is_global=True,
            hq_api_id=SQLTelerivetBackend.get_api_id()
        )
        self.backend2.set_extra_fields(
            webhook_secret='def'
        )
        self.backend2.save()

    def tearDown(self):
        self.backend1.delete()
        self.backend2.delete()

    def test_webhook_lookup(self):
        self.assertEqual(
            SQLTelerivetBackend.by_webhook_secret('abc'),
            self.backend1
        )

        self.assertEqual(
            SQLTelerivetBackend.by_webhook_secret('def'),
            self.backend2
        )

        self.assertIsNone(SQLTelerivetBackend.by_webhook_secret('ghi'))