示例#1
0
文件: models.py 项目: 3taps/Anoni-API
    def send_notifications(self):
        """ Send out notifications for this message.

            If the user has at least one device, we send out device
            notification(s) using the APN or Android gateways.  Otherwise, we
            fall back to sending out SMS notifications to each of the user's
            verified phone numbers.
        """
        from api.gateways import apn_gateway
        from api.gateways import android_gateway
        from api.gateways import sms_gateway
        from api.gateways import push_gateway

        has_device = False # initially.
        for device in Device.objects.filter(user=self.recipient.user):
            type  = device.notification_type
            token = device.notification_token

            if type == Device.TYPE_APPLE:
                apn_gateway.send_notification(text=self.body,
                                              user=self.sender.user,
                                              profile=self.sender,
                                              device_token=token,
                                              message_id=self.id)
            elif type == Device.TYPE_ANDROID:
                android_gateway.send_notification(text=self.body,
                                                  user=self.sender.user,
                                                  profile=self.sender,
                                                  device_token=token,
                                                  message_id=self.id)

            has_device = True

        if not has_device:
            # Fall back to sending SMS notifications for this message.
            for user_num in UserNumber.objects.filter(
                                                 user=self.recipient.user):
                if user_num.verified:
                    sms_gateway.send_message(text=self.body,
                                             from_user=self.sender.user,
                                             from_profile=self.sender,
                                             to_user=self.recipient.user,
                                             to_profile=self.recipient,
                                             to_phone_number=user_num.number,
                                             message_id=self.id)

        # Finally, send notification for this message out using the push
        # gateway.

        push_gateway.send_message(self)
示例#2
0
def _send_verification_code(user_num):
    """ Send the verification code to the given phone number.

        'user_num' should be the UserNumber object to send the verification
        code to.
    """
    # Find the first profile for this user.

    profiles = Profile.objects.filter(user=user_num.user)
    if len(profiles) == 0:
        first_profile = None
    else:
        first_profile = profiles[0]

    sms_gateway.send_message(text="code: " + user_num.code +
                                  " -- " + settings.SYSTEM_NAME,
                             from_user=None,
                             from_profile=None,
                             to_user=user_num.user,
                             to_profile=first_profile,
                             to_phone_number=user_num.number,
                             message_id=None)
示例#3
0
def POST_sessions(request, format):
    """ Respond to a "POST sessions" request.
    """
    params = apiHelper.get_params(request, "session")

    if "username" in params:
        error = apiHelper.check_params(params,
                                       required_params=["username",
                                                        "password"])
        login_via_username = True
    elif "number" in params:
        error = apiHelper.check_params(params,
                                       required_params=["number"],
                                       optional_params=["country"])
        login_via_username = False
    else:
        return HttpResponseBadRequest("username/password or " +
                                      "phone number required")

    if error != None: return error

    if login_via_username:

        # Log the caller in using the supplied username and password.

        username = params['username']
        password = params['password']

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            user = None

        if user == None or not user.check_password(password):
            return HttpResponseForbidden("Incorrect username or password")

        # Open up a session for this user.

        token = session.create(user)

        # Finally, return the user and the login token back to the caller.

        return apiHelper.response({'user'  : user.to_dict(),
                                   'token' : token},
                                  format=format, status=HTTP_RESPONSE_POST_OK)

    else:

        # Log the caller in using the supplied phone number.

        number = params['number']

        if "country" in params:
            country = params['country']
        else:
            country = "US"

        # Ask the "phonenumbers" library to format the phone number into E.164
        # format.

        phone_number     = phonenumbers.parse(number, country)
        phone_format     = phonenumbers.PhoneNumberFormat.E164
        formatted_number = phonenumbers.format_number(phone_number, phone_format)

        # Open up a session for this phone number.

        token,verification_code = session.create_for_phone(formatted_number)

        # Send an SMS message to the supplied phone number.

        sms_gateway.send_message(text="code: " + verification_code +
                                      " -- " + settings.SYSTEM_NAME,
                                 from_user=None,
                                 from_profile=None,
                                 to_user=None,
                                 to_profile=None,
                                 to_phone_number=formatted_number,
                                 message_id=None)

        # Finally, return the formatted phone number and login token back to
        # the caller.

        return apiHelper.response({'number'  : formatted_number,
                                   'token'   : token},
                                  format=format, status=HTTP_RESPONSE_POST_OK)
示例#4
0
    def test_sends_via_sms(self):
        """ Test the logic of sending a message via SMS.
        """
        with self.settings(ENABLE_GATEWAYS=False):

            # Create two dummy users, profiles and phone numbers for testing.

            token_1,profile_dict_1 = self.createUserAndProfile("Profile 1")
            token_2,profile_dict_2 = self.createUserAndProfile("Profile 2")

            profile_1 = Profile.objects.get(id=profile_dict_1['id'])
            user_1    = profile_1.user

            profile_2 = Profile.objects.get(id=profile_dict_2['id'])
            user_2    = profile_2.user

            number_1 = UserNumber()
            number_1.user       = user_1
            number_1.number     = self.randomDigits()
            number_1.verified   = True
            number_1.created_at = datetime.datetime.now()
            number_1.updated_at = datetime.datetime.now()
            number_1.save()

            number_2 = UserNumber()
            number_2.user       = user_2
            number_2.number     = self.randomDigits()
            number_2.verified   = True
            number_2.created_at = datetime.datetime.now()
            number_2.updated_at = datetime.datetime.now()
            number_2.save()

            # Set up a signal handler to check that the sms_message_sent signal
            # is being sent.

            self.signal_received = False # initially.
            self.payload         = None  # ditto.

            def signal_handler(sender, **kwargs):
                self.signal_received = True
                self.payload         = kwargs.get("payload")

            signals.sms_message_sent.connect(signal_handler)

            # Send a dummy message via the SMS gateway.

            sms_gateway.send_message(text="Test Message",
                                     from_user=user_1,
                                     from_profile=profile_1,
                                     to_user=user_2,
                                     to_profile=profile_2,
                                     to_phone_number=number_2.number)

            # Clean up, and check that the SMS gateway worked correctly.

            signals.sms_message_sent.disconnect(signal_handler)

            self.assertTrue(self.signal_received,
                            "Message wasn't sent via SMS gateway!")
            self.assertItemsEqual(self.payload.keys(),
                                  ["from_phone", "to_phone", "sms_text"],
                                  "Bad SMS payload!")
            self.assertEqual(self.payload['to_phone'], number_2.number,
                             "SMS text sent to the wrong number!")

            from_phone = self.payload['from_phone']
            try:
                phone_number = TwilioPhoneNumber.objects.get(number=from_phone)
            except TwilioPhoneNumber.DoesNotExist:
                phone_number = None

            self.assertIsNotNone(phone_number,
                                 "SMS sent from non-existent phone number!")

            try:
                channel = TwilioSMSChannel.objects.get(
                                                sender=profile_1,
                                                recipient=profile_2,
                                                phone_number=phone_number)
            except TwilioSMSChannel.DoesNotExist:
                channel = None

            self.assertIsNotNone(channel, "No SMS channel set up!")
示例#5
0
    def test_creates_second_sms_channel(self):
        """ Check that two users sending to a profile use different channels.
        """
        with self.settings(ENABLE_GATEWAYS=False):

            # Create three dummy users, profiles and phone numbers for testing.

            token_1,profile_dict_1 = self.createUserAndProfile("Profile 1")
            token_2,profile_dict_2 = self.createUserAndProfile("Profile 2")
            token_3,profile_dict_3 = self.createUserAndProfile("Profile 3")

            profile_1 = Profile.objects.get(id=profile_dict_1['id'])
            user_1    = profile_1.user

            profile_2 = Profile.objects.get(id=profile_dict_2['id'])
            user_2    = profile_2.user

            profile_3 = Profile.objects.get(id=profile_dict_3['id'])
            user_3    = profile_3.user

            number_1 = UserNumber()
            number_1.user       = user_1
            number_1.number     = self.randomDigits()
            number_1.verified   = True
            number_1.created_at = datetime.datetime.now()
            number_1.updated_at = datetime.datetime.now()
            number_1.save()

            number_2 = UserNumber()
            number_2.user       = user_2
            number_2.number     = self.randomDigits()
            number_2.verified   = True
            number_2.created_at = datetime.datetime.now()
            number_2.updated_at = datetime.datetime.now()
            number_2.save()

            number_3 = UserNumber()
            number_3.user       = user_3
            number_3.number     = self.randomDigits()
            number_3.verified   = True
            number_3.created_at = datetime.datetime.now()
            number_3.updated_at = datetime.datetime.now()
            number_3.save()

            # Set up a handler to grab the payload from the sms_gateway signal.

            self.signal_received = False # initially.
            self.payload         = None  # ditto.

            def signal_handler(sender, **kwargs):
                self.signal_received = True
                self.payload         = kwargs.get("payload")

            signals.sms_message_sent.connect(signal_handler)

            # Send a dummy message via the SMS gateway from profile 1 to
            # profile 3.

            sms_gateway.send_message(text="Test Message",
                                     from_user=user_1,
                                     from_profile=profile_1,
                                     to_user=user_3,
                                     to_profile=profile_3,
                                     to_phone_number=number_3.number)

            # Grab the SMS channel used to send this message.

            from_phone   = self.payload['from_phone']
            phone_number = TwilioPhoneNumber.objects.get(number=from_phone)
            channel_1    = TwilioSMSChannel.objects.get(
                                                sender=profile_1,
                                                recipient=profile_3,
                                                phone_number=phone_number)

            # Now send a second message via the SMS gateway, from profile 2 to
            # profile 3.

            self.signal_received = False
            self.payload         = None

            sms_gateway.send_message(text="Test Message",
                                     from_user=user_2,
                                     from_profile=profile_2,
                                     to_user=user_3,
                                     to_profile=profile_3,
                                     to_phone_number=number_3.number)

            # Check that a different SMS channel was used for the two messages.

            from_phone = self.payload['from_phone']
            try:
                phone_number = TwilioPhoneNumber.objects.get(number=from_phone)
            except TwilioPhoneNumber.DoesNotExist:
                phone_number = None

            try:
                channel_2 = TwilioSMSChannel.objects.get(
                                                sender=profile_2,
                                                recipient=profile_3,
                                                phone_number=phone_number)
            except TwilioSMSChannel.DoesNotExist:
                channel_2 = None

            self.assertNotEqual(channel_1, channel_2,
                             "The same channel was used for both messages!")

            # Clean up.

            signals.sms_message_sent.disconnect(signal_handler)