def test_api_request_headers(self): old_style_channel = Channel.create( self.org, self.user, 'RW', WhatsAppDirectType.code, None, '+27000000000', config=dict(api_token='api-token', secret='secret'), uuid='00000000-0000-0000-0000-000000001234', role=Channel.DEFAULT_ROLE) new_style_channel = Channel.create( self.org, self.user, 'RW', WhatsAppDirectType.code, None, '+27000000000', config={ 'authorization': { 'token_type': 'Bearer', 'access_token': 'foo', } }, uuid='00000000-0000-0000-0000-000000005678', role=Channel.DEFAULT_ROLE) t = WhatsAppDirectType() self.assertEqual( t.api_request_headers(old_style_channel)['Authorization'], 'Token api-token') self.assertEqual( t.api_request_headers(new_style_channel)['Authorization'], 'Bearer foo')
def setUp(self): self.clear_cache() self.user = self.create_user("tito") self.admin = self.create_user("Administrator") self.org = Org.objects.create(name="Nyaruka Ltd.", timezone="Africa/Kigali", created_by=self.user, modified_by=self.user) self.org.initialize() self.org.administrators.add(self.admin) self.admin.set_org(self.org) self.org.administrators.add(self.user) self.user.set_org(self.org) self.tel_mtn = Channel.create(self.org, self.user, 'RW', 'A', name="MTN", address="+250780000000", secret="12345", gcm_id="123") self.tel_tigo = Channel.create(self.org, self.user, 'RW', 'A', name="Tigo", address="+250720000000", secret="23456", gcm_id="234") self.tel_bulk = Channel.create(self.org, self.user, 'RW', 'NX', name="Nexmo", parent=self.tel_tigo) self.twitter = Channel.create(self.org, self.user, None, 'TT', name="Twitter", address="billy_bob") # for generating tuples of scheme, path and channel def generate_tel_mtn(num): return TEL_SCHEME, "+25078%07d" % (num + 1), self.tel_mtn def generate_tel_tigo(num): return TEL_SCHEME, "+25072%07d" % (num + 1), self.tel_tigo def generate_twitter(num): return TWITTER_SCHEME, "tweep_%d" % (num + 1), self.twitter self.urn_generators = (generate_tel_mtn, generate_tel_tigo, generate_twitter) self.field_nick = ContactField.get_or_create(self.org, self.admin, 'nick', 'Nickname', show_in_table=True, value_type=Value.TYPE_TEXT) self.field_age = ContactField.get_or_create(self.org, self.admin, 'age', 'Age', show_in_table=True, value_type=Value.TYPE_DECIMAL)
def test_refresh_channel_auth_tokens(self, patched_delay): # channel set for refreshing refresh_channel = Channel.create( self.org, self.user, 'RW', WhatsAppDirectType.code, None, '+27000000000', config={ "authorization": { "access_token": "a", "refresh_token": "b", }, "expires_at": datetime.now().isoformat(), }, uuid='00000000-0000-0000-0000-000000001234', role=Channel.DEFAULT_ROLE) # channel still ok Channel.create( self.org, self.user, 'RW', WhatsAppDirectType.code, None, '+27000000000', config={ "authorization": { "access_token": "a", "refresh_token": "b", }, "expires_at": ( datetime.now() + timedelta(days=5)).isoformat(), }, uuid='00000000-0000-0000-0000-000000005678', role=Channel.DEFAULT_ROLE) refresh_channel_auth_tokens() patched_delay.assert_called_with(refresh_channel.pk)
def setUp(self): super().setUp() flow = self.get_flow("ussd_example") self.starcode = "*113#" self.channel.delete() self.channel = Channel.create( self.org, self.user, "RW", "JNU", None, "1234", config=dict(username="******", password="******", send_url="http://example.org/"), uuid="00000000-0000-0000-0000-000000001234", role=Channel.ROLE_USSD, ) self.trigger, _ = Trigger.objects.get_or_create( channel=self.channel, keyword=self.starcode, flow=flow, created_by=self.user, modified_by=self.user, org=self.org, trigger_type=Trigger.TYPE_USSD_PULL, )
def setUp(self): super(JunebugUSSDTest, self).setUp() flow = self.get_flow('ussd_example') self.starcode = "*113#" self.channel.delete() self.channel = Channel.create( self.org, self.user, 'RW', Channel.TYPE_JUNEBUG_USSD, None, '1234', config=dict(username='******', password='******', send_url='http://example.org/'), uuid='00000000-0000-0000-0000-000000001234', role=Channel.ROLE_USSD) self.trigger, _ = Trigger.objects.get_or_create( channel=self.channel, keyword=self.starcode, flow=flow, created_by=self.user, modified_by=self.user, org=self.org, trigger_type=Trigger.TYPE_USSD_PULL)
def setUp(self): super(APITest, self).setUp() self.joe = self.create_contact("Joe Blow", "0788123123") self.frank = self.create_contact("Frank", twitter="franky") self.test_contact = Contact.get_test_contact(self.user) self.twitter = Channel.create(self.org, self.user, None, 'TT', name="Twitter Channel", address="billy_bob", role="SR", scheme='twitter') self.create_secondary_org() self.hans = self.create_contact("Hans Gruber", "+4921551511", org=self.org2) self.maxDiff = None # this is needed to prevent REST framework from rolling back transaction created around each unit test connection.settings_dict['ATOMIC_REQUESTS'] = False
def test_range_details(self): url = reverse('dashboard.dashboard_range_details') # visit this page without authenticating response = self.client.get(url, follow=True) # nope! self.assertRedirects(response, "/users/login/?next=%s" % url) self.login(self.admin) self.create_activity() types = ['T', 'TT', 'FB', 'NX', 'AT', 'KN', 'CK'] michael = self.create_contact("Michael", twitter="mjackson") for t in types: channel = Channel.create(self.org, self.user, None, t, name="Test Channel %s" % t, address="%s:1234" % t) self.create_msg(contact=michael, direction='O', text="Message on %s" % t, channel=channel) response = self.client.get(url) # org message activity self.assertEqual(12, response.context['orgs'][0]['count_sum']) self.assertEqual('Temba', response.context['orgs'][0]['channel__org__name']) # our pie chart self.assertEqual(5, response.context['channel_types'][0]['count_sum']) self.assertEqual('Android', response.context['channel_types'][0]['channel__name']) self.assertEqual(7, len(response.context['channel_types'])) self.assertEqual('Other', response.context['channel_types'][6]['channel__name'])
def form_valid(self, form): org = self.request.user.get_org() authorization = self.get_session_authorization() access_token = authorization['access_token'] group_uuid = form.cleaned_data['group'] [group] = [ group for group in self.get_groups(access_token) if group['uuid'] == group_uuid ] config = { 'authorization': authorization, 'expires_at': ((datetime.now() + timedelta(seconds=authorization['expires_in']))).isoformat(), 'group': group, } self.object = Channel.create( org, self.request.user, None, self.channel_type, name='group messages to %(subject)s on %(number)s' % group, address=group['number'], config=config, secret=Channel.generate_secret()) self.clear_session_authorization() return super(WhatsAppClaimView, self).form_valid(form)
def form_valid(self, form): org = self.request.user.get_org() number = form.cleaned_data['number'] authorization = self.get_session_authorization() config = { 'authorization': authorization, 'expires_at': (datetime.now() + timedelta(seconds=authorization['expires_in'])).isoformat(), 'number': number, } self.object = Channel.create(org, self.request.user, None, self.channel_type, name='Direct Messages to %s' % (number, ), address=number, config=config, secret=Channel.generate_secret()) self.clear_session_authorization return super(WhatsAppClaimView, self).form_valid(form)
def setUp(self): super(USSDSessionTest, self).setUp() self.channel.delete() self.channel = Channel.create(self.org, self.user, 'RW', 'JNU', None, '+250788123123', role=Channel.ROLE_USSD + Channel.DEFAULT_ROLE, uuid='00000000-0000-0000-0000-000000001234')
def test_add_contact_changed(self): twitter = Channel.create( self.org, self.admin, None, "TT", "Twitter", "nyaruka", schemes=["twitter", "twitterid"] ) self.contact.set_preferred_channel(twitter) self.contact.urns.filter(scheme="twitterid").update(channel=twitter) self.contact.clear_urn_cache() with patch("django.utils.timezone.now", return_value=datetime(2018, 1, 18, 14, 24, 30, 0, tzinfo=pytz.UTC)): self.contact.set_field(self.admin, "gender", "M") self.contact.set_field(self.admin, "age", 36) self.assertEqual( self.client.request_builder(self.org).add_contact_changed(self.contact).request["events"], [ { "type": "contact_changed", "created_on": "2018-01-18T14:24:30+00:00", "contact": { "uuid": str(self.contact.uuid), "id": self.contact.id, "name": "Bob", "language": None, "urns": [ "twitterid:123456785?channel=%s#bobby" % str(twitter.uuid), "tel:+12345670987?channel=%s" % str(self.channel.uuid), ], "fields": {"gender": {"text": "M"}, "age": {"text": "36", "number": "36"}}, "groups": [{"uuid": str(self.testers.uuid), "name": "Testers"}], }, } ], )
def setUp(self): super(WhatsAppDirectTypeTest, self).setUp() self.channel = Channel.create( self.org, self.user, 'RW', WhatsAppDirectType.code, None, '+27000000000', config=dict(api_token='api-token', secret='secret'), uuid='00000000-0000-0000-0000-000000001234', role=Channel.DEFAULT_ROLE)
def setUp(self): # if we are super verbose, turn on debug for sql queries if self.get_verbosity() > 2: settings.DEBUG = True self.clear_cache() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # create different user types self.non_org_user = self.create_user("NonOrg") self.user = self.create_user("User") self.editor = self.create_user("Editor") self.admin = self.create_user("Administrator") self.surveyor = self.create_user("Surveyor") # setup admin boundaries for Rwanda self.country = AdminBoundary.objects.create(osm_id='171496', name='Rwanda', level=0) self.state1 = AdminBoundary.objects.create(osm_id='1708283', name='Kigali City', level=1, parent=self.country) self.state2 = AdminBoundary.objects.create(osm_id='171591', name='Eastern Province', level=1, parent=self.country) self.district1 = AdminBoundary.objects.create(osm_id='1711131', name='Gatsibo', level=2, parent=self.state2) self.district2 = AdminBoundary.objects.create(osm_id='1711163', name='Kayônza', level=2, parent=self.state2) self.district3 = AdminBoundary.objects.create(osm_id='3963734', name='Nyarugenge', level=2, parent=self.state1) self.district4 = AdminBoundary.objects.create(osm_id='1711142', name='Rwamagana', level=2, parent=self.state2) self.ward1 = AdminBoundary.objects.create(osm_id='171113181', name='Kageyo', level=3, parent=self.district1) self.ward2 = AdminBoundary.objects.create(osm_id='171116381', name='Kabare', level=3, parent=self.district2) self.ward3 = AdminBoundary.objects.create(osm_id='171114281', name='Bukure', level=3, parent=self.district4) self.org = Org.objects.create(name="Temba", timezone=pytz.timezone("Africa/Kigali"), country=self.country, brand=settings.DEFAULT_BRAND, created_by=self.user, modified_by=self.user) self.org.initialize(topup_size=1000) # add users to the org self.user.set_org(self.org) self.org.viewers.add(self.user) self.editor.set_org(self.org) self.org.editors.add(self.editor) self.admin.set_org(self.org) self.org.administrators.add(self.admin) self.surveyor.set_org(self.org) self.org.surveyors.add(self.surveyor) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.topups.all()[0] # a single Android channel self.channel = Channel.create(self.org, self.user, 'RW', 'A', name="Test Channel", address="+250785551212", device="Nexus 5X", secret="12345", gcm_id="123") # reset our simulation to False Contact.set_simulation(False)
def setUp(self): # if we are super verbose, turn on debug for sql queries if self.get_verbosity() > 2: settings.DEBUG = True self.clear_cache() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # create different user types self.non_org_user = self.create_user("NonOrg") self.user = self.create_user("User") self.editor = self.create_user("Editor") self.admin = self.create_user("Administrator") self.surveyor = self.create_user("Surveyor") # setup admin boundaries for Rwanda self.country = AdminBoundary.objects.create(osm_id='171496', name='Rwanda', level=0) self.state1 = AdminBoundary.objects.create(osm_id='1708283', name='Kigali City', level=1, parent=self.country) self.state2 = AdminBoundary.objects.create(osm_id='171591', name='Eastern Province', level=1, parent=self.country) self.district1 = AdminBoundary.objects.create(osm_id='1711131', name='Gatsibo', level=2, parent=self.state2) self.district2 = AdminBoundary.objects.create(osm_id='1711163', name='Kayônza', level=2, parent=self.state2) self.district3 = AdminBoundary.objects.create(osm_id='3963734', name='Nyarugenge', level=2, parent=self.state1) self.district4 = AdminBoundary.objects.create(osm_id='1711142', name='Rwamagana', level=2, parent=self.state2) self.ward1 = AdminBoundary.objects.create(osm_id='171113181', name='Kageyo', level=3, parent=self.district1) self.ward2 = AdminBoundary.objects.create(osm_id='171116381', name='Kabare', level=3, parent=self.district2) self.ward3 = AdminBoundary.objects.create(osm_id='171114281', name='Bukure', level=3, parent=self.district4) self.org = Org.objects.create(name="Temba", timezone="Africa/Kigali", country=self.country, brand=settings.DEFAULT_BRAND, created_by=self.user, modified_by=self.user) self.org.initialize(topup_size=1000) # add users to the org self.user.set_org(self.org) self.org.viewers.add(self.user) self.editor.set_org(self.org) self.org.editors.add(self.editor) self.admin.set_org(self.org) self.org.administrators.add(self.admin) self.surveyor.set_org(self.org) self.org.surveyors.add(self.surveyor) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.topups.all()[0] # a single Android channel self.channel = Channel.create(self.org, self.user, 'RW', 'A', name="Test Channel", address="+250785551212", device="Nexus 5X", secret="12345", gcm_id="123") # reset our simulation to False Contact.set_simulation(False)
def claim_number(self, user, phone_number, country, role): auth_id = self.request.session.get(Channel.CONFIG_PLIVO_AUTH_ID, None) auth_token = self.request.session.get(Channel.CONFIG_PLIVO_AUTH_TOKEN, None) org = user.get_org() plivo_uuid = generate_uuid() callback_domain = org.get_brand_domain() app_name = "%s/%s" % (callback_domain.lower(), plivo_uuid) message_url = "https://" + callback_domain + "%s" % reverse('handlers.plivo_handler', args=['receive', plivo_uuid]) answer_url = "https://" + settings.AWS_BUCKET_DOMAIN + "/plivo_voice_unavailable.xml" headers = http_headers(extra={'Content-Type': "application/json"}) create_app_url = "https://api.plivo.com/v1/Account/%s/Application/" % auth_id response = requests.post(create_app_url, json=dict(app_name=app_name, answer_url=answer_url, message_url=message_url), headers=headers, auth=(auth_id, auth_token)) if response.status_code in [201, 200, 202]: plivo_app_id = response.json()['app_id'] else: # pragma: no cover plivo_app_id = None plivo_config = {Channel.CONFIG_PLIVO_AUTH_ID: auth_id, Channel.CONFIG_PLIVO_AUTH_TOKEN: auth_token, Channel.CONFIG_PLIVO_APP_ID: plivo_app_id, Channel.CONFIG_CALLBACK_DOMAIN: org.get_brand_domain()} plivo_number = phone_number.strip('+ ').replace(' ', '') response = requests.get("https://api.plivo.com/v1/Account/%s/Number/%s/" % (auth_id, plivo_number), headers=headers, auth=(auth_id, auth_token)) if response.status_code != 200: response = requests.post("https://api.plivo.com/v1/Account/%s/PhoneNumber/%s/" % (auth_id, plivo_number), headers=headers, auth=(auth_id, auth_token)) if response.status_code != 201: # pragma: no cover raise Exception(_("There was a problem claiming that number, please check the balance on your account.")) response = requests.get("https://api.plivo.com/v1/Account/%s/Number/%s/" % (auth_id, plivo_number), headers=headers, auth=(auth_id, auth_token)) if response.status_code == 200: response = requests.post("https://api.plivo.com/v1/Account/%s/Number/%s/" % (auth_id, plivo_number), json=dict(app_id=plivo_app_id), headers=headers, auth=(auth_id, auth_token)) if response.status_code != 202: # pragma: no cover raise Exception(_("There was a problem updating that number, please try again.")) phone_number = '+' + plivo_number phone = phonenumbers.format_number(phonenumbers.parse(phone_number, None), phonenumbers.PhoneNumberFormat.NATIONAL) channel = Channel.create(org, user, country, 'PL', name=phone, address=phone_number, config=plivo_config, uuid=plivo_uuid) analytics.track(user.username, 'temba.channel_claim_plivo', dict(number=phone_number)) return channel
def setUp(self): super(VumiUssdTest, self).setUp() self.channel.delete() self.channel = Channel.create(self.org, self.user, 'RW', 'VMU', None, '+250788123123', config=dict(account_key='vumi-key', access_token='vumi-token', conversation_key='key'), uuid='00000000-0000-0000-0000-000000001234', role=Channel.ROLE_USSD)
def claim_number(self, user, phone_number, country, role): auth_id = self.request.session.get(Channel.CONFIG_PLIVO_AUTH_ID, None) auth_token = self.request.session.get(Channel.CONFIG_PLIVO_AUTH_TOKEN, None) org = user.get_org() plivo_uuid = generate_uuid() app_name = "%s/%s" % (settings.TEMBA_HOST.lower(), plivo_uuid) client = plivo.RestAPI(auth_id, auth_token) message_url = "https://" + settings.TEMBA_HOST + "%s" % reverse('handlers.plivo_handler', args=['receive', plivo_uuid]) answer_url = "https://" + settings.AWS_BUCKET_DOMAIN + "/plivo_voice_unavailable.xml" plivo_response_status, plivo_response = client.create_application(params=dict(app_name=app_name, answer_url=answer_url, message_url=message_url)) if plivo_response_status in [201, 200, 202]: plivo_app_id = plivo_response['app_id'] else: # pragma: no cover plivo_app_id = None plivo_config = {Channel.CONFIG_PLIVO_AUTH_ID: auth_id, Channel.CONFIG_PLIVO_AUTH_TOKEN: auth_token, Channel.CONFIG_PLIVO_APP_ID: plivo_app_id} plivo_number = phone_number.strip('+ ').replace(' ', '') plivo_response_status, plivo_response = client.get_number(params=dict(number=plivo_number)) if plivo_response_status != 200: plivo_response_status, plivo_response = client.buy_phone_number(params=dict(number=plivo_number)) if plivo_response_status != 201: # pragma: no cover raise Exception(_("There was a problem claiming that number, please check the balance on your account.")) plivo_response_status, plivo_response = client.get_number(params=dict(number=plivo_number)) if plivo_response_status == 200: plivo_response_status, plivo_response = client.modify_number(params=dict(number=plivo_number, app_id=plivo_app_id)) if plivo_response_status != 202: # pragma: no cover raise Exception(_("There was a problem updating that number, please try again.")) phone_number = '+' + plivo_number phone = phonenumbers.format_number(phonenumbers.parse(phone_number, None), phonenumbers.PhoneNumberFormat.NATIONAL) channel = Channel.create(org, user, country, 'PL', name=phone, address=phone_number, config=plivo_config, uuid=plivo_uuid) analytics.track(user.username, 'temba.channel_claim_plivo', dict(number=phone_number)) return channel
def browser(self): self.driver.set_window_size(1024, 2000) # view the homepage self.fetch_page() # go directly to our signup self.fetch_page(reverse("orgs.org_signup")) # create account self.keys("email", "*****@*****.**") self.keys("password", "SuperSafe1") self.keys("first_name", "Joe") self.keys("last_name", "Blow") self.click("#form-one-submit") self.keys("name", "Temba") self.click("#form-two-submit") # set up our channel for claiming channel = Channel.create( None, get_anonymous_user(), "RW", "A", name="Test Channel", address="0785551212", claim_code="AAABBBCCC", secret="12345", gcm_id="123", ) # and claim it self.fetch_page(reverse("channels.channel_claim_android")) self.keys("#id_claim_code", "AAABBBCCC") self.keys("#id_phone_number", "0785551212") self.submit(".claim-form") # get our freshly claimed channel channel = Channel.objects.get(pk=channel.pk) # now go to the contacts page self.click("#menu-right .icon-contact") self.click("#id_import_contacts") # upload some contacts directory = os.path.dirname(os.path.realpath(__file__)) self.keys("#csv_file", "%s/../media/test_imports/sample_contacts.xls" % directory) self.submit(".smartmin-form") # make sure they are there self.click("#menu-right .icon-contact") self.assertInElements(".value-phone", "+250788382382") self.assertInElements(".value-text", "Eric Newcomer") self.assertInElements(".value-text", "Sample Contacts")
def browser(self): self.driver.set_window_size(1024, 2000) # view the homepage self.fetch_page() # go directly to our signup self.fetch_page(reverse('orgs.org_signup')) # create account self.keys('email', '*****@*****.**') self.keys('password', 'SuperSafe1') self.keys('first_name', 'Joe') self.keys('last_name', 'Blow') self.click('#form-one-submit') self.keys('name', 'Temba') self.click('#form-two-submit') # set up our channel for claiming anon = User.objects.get(pk=settings.ANONYMOUS_USER_ID) channel = Channel.create(None, anon, 'RW', 'A', name="Test Channel", address="0785551212", claim_code='AAABBBCCC', secret="12345", gcm_id="123") # and claim it self.fetch_page(reverse('channels.channel_claim_android')) self.keys('#id_claim_code', 'AAABBBCCC') self.keys('#id_phone_number', '0785551212') self.submit('.claim-form') # get our freshly claimed channel channel = Channel.objects.get(pk=channel.pk) # now go to the contacts page self.click('#menu-right .icon-contact') self.click('#id_import_contacts') # upload some contacts directory = os.path.dirname(os.path.realpath(__file__)) self.keys('#csv_file', '%s/../media/test_imports/sample_contacts.xls' % directory) self.submit('.smartmin-form') # make sure they are there self.click('#menu-right .icon-contact') self.assertInElements('.value-phone', '+250788382382') self.assertInElements('.value-text', 'Eric Newcomer') self.assertInElements('.value-text', 'Sample Contacts')
def setUp(self): super(ContactRefreshTaskTestCase, self).setUp() self.old_style_channel = Channel.create( self.org, self.user, 'RW', WhatsAppDirectType.code, None, '+27000000000', config=dict(api_token='api-token', secret='secret'), uuid='00000000-0000-0000-0000-000000001234', role=Channel.DEFAULT_ROLE) self.new_style_channel = Channel.create( self.org, self.user, 'RW', WhatsAppDirectType.code, None, '+27000000000', config={ 'authorization': { 'token_type': 'Bearer', 'access_token': 'foo', } }, uuid='00000000-0000-0000-0000-000000005678', role=Channel.DEFAULT_ROLE)
def test_new_conversation_trigger(self): self.login(self.admin) flow = self.create_flow() flow2 = self.create_flow() # see if we list new conversation triggers on the trigger page create_trigger_url = reverse("triggers.trigger_create", args=[]) response = self.client.get(create_trigger_url) self.assertNotContains(response, "conversation is started") # create a facebook channel fb_channel = Channel.create( self.org, self.user, None, "FB", address="1001", config={"page_name": "Temba", "auth_token": "fb_token"} ) # should now be able to create one response = self.client.get(create_trigger_url) self.assertContains(response, "conversation is started") # go create it with patch("requests.post") as mock_post: mock_post.return_value = MockResponse(200, '{"message": "Success"}') response = self.client.post( reverse("triggers.trigger_new_conversation", args=[]), data=dict(channel=fb_channel.id, flow=flow.id) ) self.assertEqual(response.status_code, 200) self.assertEqual(mock_post.call_count, 1) # check that it is right trigger = Trigger.objects.get( trigger_type=Trigger.TYPE_NEW_CONVERSATION, is_active=True, is_archived=False ) self.assertEqual(trigger.channel, fb_channel) self.assertEqual(trigger.flow, flow) # try to create another one, fails as we already have a trigger for that channel response = self.client.post( reverse("triggers.trigger_new_conversation", args=[]), data=dict(channel=fb_channel.id, flow=flow2.id) ) self.assertEqual(response.status_code, 200) self.assertFormError(response, "form", "channel", "Trigger with this Channel already exists.") # archive our trigger, should unregister our callback with patch("requests.post") as mock_post: mock_post.return_value = MockResponse(200, '{"message": "Success"}') Trigger.apply_action_archive(self.admin, Trigger.objects.filter(pk=trigger.pk)) self.assertEqual(response.status_code, 200) self.assertEqual(mock_post.call_count, 1) trigger.refresh_from_db() self.assertTrue(trigger.is_archived)
def test_channels(self): url = reverse('api.v2.channels') self.assertEndpointAccess(url) # create channel for other org Channel.create(self.org2, self.admin2, None, 'TT', name="Twitter Channel", address="nyaruka", role="SR", scheme='twitter') # no filtering with self.assertNumQueries(NUM_BASE_REQUEST_QUERIES + 2): response = self.fetchJSON(url) self.assertEqual(response.status_code, 200) self.assertEqual(response.json['next'], None) self.assertResultsByUUID(response, [self.twitter, self.channel]) self.assertEqual(response.json['results'][1], { 'uuid': self.channel.uuid, 'name': "Test Channel", 'address': "+250785551212", 'country': "RW", 'device': { 'name': "Nexus 5X", 'network_type': None, 'power_level': -1, 'power_source': None, 'power_status': None }, 'last_seen': format_datetime(self.channel.last_seen), 'created_on': format_datetime(self.channel.created_on) }) # filter by UUID response = self.fetchJSON(url, 'uuid=%s' % self.twitter.uuid) self.assertResultsByUUID(response, [self.twitter]) # filter by address response = self.fetchJSON(url, 'address=billy_bob') self.assertResultsByUUID(response, [self.twitter])
def setUp(self): super().setUp() self.channel.delete() self.channel = Channel.create( self.org, self.user, "RW", "JNU", None, "+250788123123", role=Channel.ROLE_USSD + Channel.DEFAULT_ROLE, uuid="00000000-0000-0000-0000-000000001234", )
def setUp(self): super(DirectHandlerTest, self).setUp() self.factory = RequestFactory() self.handler = WhatsAppHandler() self.channel = Channel.create( self.org, self.user, 'RW', WhatsAppDirectType.code, None, '+27000000000', config=dict(access_token='access-token', secret='secret'), uuid='00000000-0000-0000-0000-000000001234', role=Channel.DEFAULT_ROLE)
def setUp(self): self.clear_cache() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # create different user types self.non_org_user = self.create_user("NonOrg") self.user = self.create_user("User") self.editor = self.create_user("Editor") self.admin = self.create_user("Administrator") self.surveyor = self.create_user("Surveyor") # setup admin boundaries for Rwanda self.country = AdminBoundary.objects.create(osm_id='171496', name='Rwanda', level=0) self.state1 = AdminBoundary.objects.create(osm_id='1708283', name='Kigali City', level=1, parent=self.country) self.state2 = AdminBoundary.objects.create(osm_id='171591', name='Eastern Province', level=1, parent=self.country) self.district1 = AdminBoundary.objects.create(osm_id='1711131', name='Gatsibo', level=2, parent=self.state2) self.district2 = AdminBoundary.objects.create(osm_id='1711163', name='Kayonza', level=2, parent=self.state2) self.district3 = AdminBoundary.objects.create(osm_id='60485579', name='Kigali', level=2, parent=self.state1) self.district4 = AdminBoundary.objects.create(osm_id='1711142', name='Rwamagana', level=2, parent=self.state2) self.org = Org.objects.create(name="Temba", timezone="Africa/Kigali", country=self.country, created_by=self.user, modified_by=self.user) self.org.initialize() # add users to the org self.user.set_org(self.org) self.org.viewers.add(self.user) self.editor.set_org(self.org) self.org.editors.add(self.editor) self.admin.set_org(self.org) self.org.administrators.add(self.admin) self.surveyor.set_org(self.org) self.org.surveyors.add(self.surveyor) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.topups.all()[0] # a single Android channel self.channel = Channel.create(self.org, self.user, 'RW', 'A', name="Test Channel", address="+250785551212", secret="12345", gcm_id="123") # reset our simulation to False Contact.set_simulation(False)
def setUp(self): self.clear_cache() self.user = self.create_user("tito") self.admin = self.create_user("Administrator") self.org = Org.objects.create( name="Nyaruka Ltd.", timezone="Africa/Kigali", created_by=self.user, modified_by=self.user ) self.org.initialize() self.org.administrators.add(self.admin) self.admin.set_org(self.org) self.org.administrators.add(self.user) self.user.set_org(self.org) self.tel_mtn = Channel.create( self.org, self.user, "RW", "A", name="MTN", address="+250780000000", secret="12345", gcm_id="123" ) self.tel_tigo = Channel.create( self.org, self.user, "RW", "A", name="Tigo", address="+250720000000", secret="23456", gcm_id="234" ) self.tel_bulk = Channel.create(self.org, self.user, "RW", "NX", name="Nexmo", parent=self.tel_tigo) self.twitter = Channel.create(self.org, self.user, None, "TT", name="Twitter", address="billy_bob") # for generating tuples of scheme, path and channel generate_tel_mtn = lambda num: (TEL_SCHEME, "+25078%07d" % (num + 1), self.tel_mtn) generate_tel_tigo = lambda num: (TEL_SCHEME, "+25072%07d" % (num + 1), self.tel_tigo) generate_twitter = lambda num: (TWITTER_SCHEME, "tweep_%d" % (num + 1), self.twitter) self.urn_generators = (generate_tel_mtn, generate_tel_tigo, generate_twitter) self.field_nick = ContactField.get_or_create( self.org, self.admin, "nick", "Nickname", show_in_table=True, value_type=TEXT ) self.field_age = ContactField.get_or_create( self.org, self.admin, "age", "Age", show_in_table=True, value_type=DECIMAL )
def form_valid(self, form): org = self.request.user.get_org() data = form.cleaned_data config = {Channel.CONFIG_USERNAME: data["username"], Channel.CONFIG_PASSWORD: data["password"]} self.object = Channel.create( org=org, user=self.request.user, country=data["country"], channel_type="MT", name=data["service_id"], address=data["service_id"], config=config, schemes=[TEL_SCHEME], ) return super().form_valid(form)
def new_channel(self, config=None) -> Channel: if not config: config = { RocketChatType.CONFIG_BASE_URL: self.new_url(self.domain), RocketChatType.CONFIG_BOT_USERNAME: self.bot_username, RocketChatType.CONFIG_ADMIN_AUTH_TOKEN: self.admin_auth_token, RocketChatType.CONFIG_ADMIN_USER_ID: self.admin_user_id, RocketChatType.CONFIG_SECRET: self.secret, } return Channel.create( org=self.org, user=self.user, country=None, channel_type=RocketChatType.code, name="Name", config=config or {}, )
def form_valid(self, form): org = self.request.user.get_org() data = form.cleaned_data config = {Channel.CONFIG_USERNAME: data["username"], Channel.CONFIG_AUTH_TOKEN: data["token"]} self.object = Channel.create( org=org, user=self.request.user, country=data["country"], channel_type=self.channel_type, name=data["number"], address=data["number"], config=config, schemes=[URN.TEL_SCHEME], ) return super(ClaimViewMixin, self).form_valid(form)
def form_valid(self, form): org = self.request.user.get_org() data = form.cleaned_data config = { Channel.CONFIG_USERNAME: data['username'], Channel.CONFIG_PASSWORD: data['password'], } self.object = Channel.create(org=org, user=self.request.user, country=data['country'], channel_type='MT', name=data['service_id'], address=data['service_id'], config=config, schemes=[TEL_SCHEME]) return super(ClaimViewMixin, self).form_valid(form)
def test_search(self, mock_search_numbers): self.login(self.admin) self.org.channels.update(is_active=False) self.channel = Channel.create( self.org, self.user, "RW", "NX", None, "+250788123123", uuid="00000000-0000-0000-0000-000000001234") self.org.connect_vonage("1234", "secret", self.admin) search_url = reverse("channels.types.vonage.search") response = self.client.get(search_url) self.assertEqual(["country", "pattern", "loc"], list(response.context["form"].fields.keys())) mock_search_numbers.return_value = [ { "features": ["SMS", "VOICE"], "type": "mobile-lvn", "country": "US", "msisdn": "13607884540" }, { "features": ["SMS", "VOICE"], "type": "mobile-lvn", "country": "US", "msisdn": "13607884550" }, ] response = self.client.post(search_url, { "country": "US", "pattern": "360" }) self.assertEqual(["+1 360-788-4540", "+1 360-788-4550"], response.json())
def test_refresh_token(self): def cb(request): data = urlparse.parse_qs(request.body) self.assertEqual(data['grant_type'], ['refresh_token']) self.assertEqual(data['refresh_token'], ['b']) return (200, {}, json.dumps({ 'access_token': 'foo', 'refresh_token': 'bar', 'expires_in': 3600, })) responses.add_callback( responses.POST, 'https://wassup.p16n.org/oauth/token/', callback=cb, content_type='application/json') channel = Channel.create( self.org, self.user, 'RW', WhatsAppDirectType.code, None, '+27000000000', config={ "authorization": { "access_token": "a", "refresh_token": "b", }, "expires_at": datetime.now().isoformat(), }, uuid='00000000-0000-0000-0000-000000001234', role=Channel.DEFAULT_ROLE) refresh_channel_auth_token(channel.pk) old_config = channel.config_json() channel.refresh_from_db() new_config = channel.config_json() new_authorization = new_config['authorization'] self.assertEqual(new_authorization['access_token'], 'foo') self.assertEqual(new_authorization['refresh_token'], 'bar') self.assertEqual(new_authorization['expires_in'], 3600) self.assertTrue( new_config['expires_at'] > old_config['expires_at'])
def test_range_details(self): url = reverse("dashboard.dashboard_range_details") # visit this page without authenticating response = self.client.get(url, follow=True) # nope! self.assertRedirects(response, "/users/login/?next=%s" % url) self.login(self.admin) self.create_activity() types = ["T", "TT", "FB", "NX", "AT", "KN", "CK"] michael = self.create_contact("Michael", twitter="mjackson") for t in types: channel = Channel.create(self.org, self.user, None, t, name="Test Channel %s" % t, address="%s:1234" % t) self.create_msg(contact=michael, direction="O", text="Message on %s" % t, channel=channel) response = self.client.get(url) # org message activity self.assertEqual(12, response.context["orgs"][0]["count_sum"]) self.assertEqual("Temba", response.context["orgs"][0]["channel__org__name"]) # our pie chart self.assertEqual(5, response.context["channel_types"][0]["count_sum"]) self.assertEqual("Android", response.context["channel_types"][0]["channel__name"]) self.assertEqual(7, len(response.context["channel_types"])) self.assertEqual("Other", response.context["channel_types"][6]["channel__name"])
def form_valid(self, form): org = self.request.user.get_org() data = form.cleaned_data config = { Channel.CONFIG_USERNAME: data["username"], Channel.CONFIG_PASSWORD: data["password"], "service_id": data["service_id"], "charging_level": data["charging_level"], } self.object = Channel.create( org=org, user=self.request.user, country=data["country"], channel_type=self.channel_type, name=data["shortcode"], address=data["shortcode"], config=config, schemes=[URN.TEL_SCHEME], ) return super(ClaimViewMixin, self).form_valid(form)
def setUp(self): self.maxDiff = 4096 self.mock_server = mock_server # if we are super verbose, turn on debug for sql queries if self.get_verbosity() > 2: settings.DEBUG = True # make sure we start off without any service users Group.objects.get(name="Service Users").user_set.clear() self.clear_cache() self.create_anonymous_user() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # create different user types self.non_org_user = self.create_user("NonOrg") self.user = self.create_user("User") self.editor = self.create_user("Editor") self.admin = self.create_user("Administrator") self.surveyor = self.create_user("Surveyor") self.customer_support = self.create_user("support", ("Customer Support",)) # setup admin boundaries for Rwanda self.country = AdminBoundary.create(osm_id="171496", name="Rwanda", level=0) self.state1 = AdminBoundary.create(osm_id="1708283", name="Kigali City", level=1, parent=self.country) self.state2 = AdminBoundary.create(osm_id="171591", name="Eastern Province", level=1, parent=self.country) self.district1 = AdminBoundary.create(osm_id="R1711131", name="Gatsibo", level=2, parent=self.state2) self.district2 = AdminBoundary.create(osm_id="1711163", name="Kayônza", level=2, parent=self.state2) self.district3 = AdminBoundary.create(osm_id="3963734", name="Nyarugenge", level=2, parent=self.state1) self.district4 = AdminBoundary.create(osm_id="1711142", name="Rwamagana", level=2, parent=self.state2) self.ward1 = AdminBoundary.create(osm_id="171113181", name="Kageyo", level=3, parent=self.district1) self.ward2 = AdminBoundary.create(osm_id="171116381", name="Kabare", level=3, parent=self.district2) self.ward3 = AdminBoundary.create(osm_id="VMN.49.1_1", name="Bukure", level=3, parent=self.district4) self.country.update_path() self.org = Org.objects.create( name="Temba", timezone=pytz.timezone("Africa/Kigali"), country=self.country, brand=settings.DEFAULT_BRAND, created_by=self.user, modified_by=self.user, ) self.org.initialize(topup_size=1000) # add users to the org self.user.set_org(self.org) self.org.viewers.add(self.user) self.editor.set_org(self.org) self.org.editors.add(self.editor) self.admin.set_org(self.org) self.org.administrators.add(self.admin) self.surveyor.set_org(self.org) self.org.surveyors.add(self.surveyor) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.topups.all()[0] # a single Android channel self.channel = Channel.create( self.org, self.user, "RW", "A", name="Test Channel", address="+250785551212", device="Nexus 5X", secret="12345", gcm_id="123", ) # don't cache anon user between tests from temba import utils utils._anon_user = None clear_flow_users() # reset our simulation to False Contact.set_simulation(False)
def claim_number(self, user, phone_number, country, role): org = user.get_org() client = org.get_nexmo_client() org_config = org.config app_id = org_config.get(NEXMO_APP_ID) nexmo_phones = client.get_numbers(phone_number) is_shortcode = False # try it with just the national code (for short codes) if not nexmo_phones: parsed = phonenumbers.parse(phone_number, None) shortcode = str(parsed.national_number) nexmo_phones = client.get_numbers(shortcode) if nexmo_phones: is_shortcode = True phone_number = shortcode # buy the number if we have to if not nexmo_phones: try: client.buy_nexmo_number(country, phone_number) except Exception as e: raise Exception( _( "There was a problem claiming that number, " "please check the balance on your account. " + "Note that you can only claim numbers after " "adding credit to your Nexmo account." ) + "\n" + str(e) ) channel_uuid = generate_uuid() callback_domain = org.get_brand_domain() new_receive_url = "https://" + callback_domain + reverse("courier.nx", args=[channel_uuid, "receive"]) nexmo_phones = client.get_numbers(phone_number) features = [elt.upper() for elt in nexmo_phones[0]["features"]] role = "" if "SMS" in features: role += Channel.ROLE_SEND + Channel.ROLE_RECEIVE if "VOICE" in features: role += Channel.ROLE_ANSWER + Channel.ROLE_CALL # update the delivery URLs for it try: client.update_nexmo_number(country, phone_number, new_receive_url, app_id) except Exception as e: # pragma: no cover # shortcodes don't seem to claim right on nexmo, move forward anyways if not is_shortcode: raise Exception( _("There was a problem claiming that number, please check the balance on your account.") + "\n" + str(e) ) if is_shortcode: phone = phone_number nexmo_phone_number = phone_number else: parsed = phonenumbers.parse(phone_number, None) phone = phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.INTERNATIONAL) # nexmo ships numbers around as E164 without the leading + nexmo_phone_number = phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.E164).strip("+") config = { Channel.CONFIG_NEXMO_APP_ID: app_id, Channel.CONFIG_NEXMO_APP_PRIVATE_KEY: org_config[NEXMO_APP_PRIVATE_KEY], Channel.CONFIG_NEXMO_API_KEY: org_config[NEXMO_KEY], Channel.CONFIG_NEXMO_API_SECRET: org_config[NEXMO_SECRET], Channel.CONFIG_CALLBACK_DOMAIN: callback_domain, } channel = Channel.create( org, user, country, "NX", name=phone, address=phone_number, role=role, config=config, bod=nexmo_phone_number, uuid=channel_uuid, tps=1, ) analytics.track(user.username, "temba.channel_claim_nexmo", dict(number=phone_number)) return channel
def claim_number(self, user, phone_number, country, role): auth_id = self.request.session.get(Channel.CONFIG_PLIVO_AUTH_ID, None) auth_token = self.request.session.get(Channel.CONFIG_PLIVO_AUTH_TOKEN, None) org = user.get_org() plivo_uuid = generate_uuid() callback_domain = org.get_brand_domain() app_name = "%s/%s" % (callback_domain.lower(), plivo_uuid) message_url = "https://" + callback_domain + "%s" % reverse("courier.pl", args=[plivo_uuid, "receive"]) answer_url = "https://" + settings.TEMBA_HOST+settings.MEDIA_URL+ "plivo_voice_unavailable.xml" headers = http_headers(extra={"Content-Type": "application/json"}) create_app_url = "https://api.plivo.com/v1/Account/%s/Application/" % auth_id response = requests.post( create_app_url, json=dict(app_name=app_name, answer_url=answer_url, message_url=message_url), headers=headers, auth=(auth_id, auth_token), ) if response.status_code in [201, 200, 202]: plivo_app_id = response.json()["app_id"] else: # pragma: no cover plivo_app_id = None plivo_config = { Channel.CONFIG_PLIVO_AUTH_ID: auth_id, Channel.CONFIG_PLIVO_AUTH_TOKEN: auth_token, Channel.CONFIG_PLIVO_APP_ID: plivo_app_id, Channel.CONFIG_CALLBACK_DOMAIN: org.get_brand_domain(), } plivo_number = phone_number.strip("+ ").replace(" ", "") response = requests.get( "https://api.plivo.com/v1/Account/%s/Number/%s/" % (auth_id, plivo_number), headers=headers, auth=(auth_id, auth_token), ) if response.status_code != 200: response = requests.post( "https://api.plivo.com/v1/Account/%s/PhoneNumber/%s/" % (auth_id, plivo_number), headers=headers, auth=(auth_id, auth_token), ) if response.status_code != 201: # pragma: no cover raise Exception( _("There was a problem claiming that number, please check the balance on your account.") ) response = requests.get( "https://api.plivo.com/v1/Account/%s/Number/%s/" % (auth_id, plivo_number), headers=headers, auth=(auth_id, auth_token), ) if response.status_code == 200: response = requests.post( "https://api.plivo.com/v1/Account/%s/Number/%s/" % (auth_id, plivo_number), json=dict(app_id=plivo_app_id), headers=headers, auth=(auth_id, auth_token), ) if response.status_code != 202: # pragma: no cover raise Exception(_("There was a problem updating that number, please try again.")) phone_number = "+" + plivo_number phone = phonenumbers.format_number( phonenumbers.parse(phone_number, None), phonenumbers.PhoneNumberFormat.NATIONAL ) channel = Channel.create( org, user, country, "PL", name=phone, address=phone_number, config=plivo_config, uuid=plivo_uuid ) analytics.track(user.username, "temba.channel_claim_plivo", dict(number=phone_number)) return channel