Ejemplo n.º 1
0
def POST_user_numbers(request, format):
    """ Respond to a "POST user_numbers" request.
    """
    params = apiHelper.get_params(request, "user_number")

    error = apiHelper.check_params(params,
                                   required_params=["token", "number"],
                                   optional_params=["country"])
    if error != None: return error

    token   = params['token']
    number  = params['number']

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

    if not session.validate(token):
        return HttpResponseBadRequest("Invalid token")

    user = session.get_user(token)

    # 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)

    # If we already have a UserNumber record for this phone number, delete the
    # old one.

    try:
        user_num = UserNumber.objects.get(number=formatted_number)
    except UserNumber.DoesNotExist:
        user_num = None

    if user_num != None:
        user_num.delete() # ??? What if the number is owned by someone else?

    # Create the UserNumber record for this phone number.

    user_num = UserNumber()
    user_num.user       = user
    user_num.number     = formatted_number
    user_num.code       = utils.calc_random_digits(num_digits=4)
    user_num.verified   =  False
    user_num.created_at = datetime.datetime.now()
    user_num.updated_at = datetime.datetime.now()
    user_num.save()

    # Ask our SMS gateway to send a verification message to the phone.

    _send_verification_code(user_num)

    # Finally, return the newly-created user number back to the caller.

    return apiHelper.response({'user_number' : user_num.to_dict()},
                              format=format, status=HTTP_RESPONSE_POST_OK)
Ejemplo n.º 2
0
    def test_create_conversation_no_account(self):
        """ Test the "POST /conversations" call when one party has no account.
        """
        # Create the first user.

        token,profile = self.createUserAndProfile("Profile 1")

        # Set up a phone number to use for testing.  Note that we use the
        # "phonenumbers" library to convert the number to E.164 format, so we
        # can find the formatted number again.

        raw_phone_number = "64212772641"

        phone_number = phonenumbers.parse(raw_phone_number, "US")
        phone_format = phonenumbers.PhoneNumberFormat.E164
        formatted_number = phonenumbers.format_number(phone_number,
                                                      phone_format)

        # Now create the conversation, supplying only the raw phone number for
        # the second user.

        response = self.sendRequest("POST", "/conversations",
                                    {'token'    : token,
                                     'number'   : raw_phone_number,
                                     'sender_id': profile['id']})

        self.assertEqual(response.status_code, HTTP_RESPONSE_POST_OK)
        self.assertEqual(response['Content-Type'], "application/json")

        conversation = json.loads(response.content)['conversation']

        # Check that a user and profile have been created for the second user.

        other_profile_id = conversation['profile_id']
        try:
            other_profile = Profile.objects.get(id=other_profile_id)
        except Profile.DoesNotExist:
            self.fail("Didn't create profile for other party.")

        other_user = other_profile.user

        found = False
        for number in UserNumber.objects.filter(user=other_user):
            if number.number == formatted_number:
                found = True

        self.assertTrue(found)
Ejemplo n.º 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)
Ejemplo n.º 4
0
def POST_conversations(request, format):
    """ Respond to the "POST conversations" request.
    """
    # Get the request parameters.

    params = apiHelper.get_params(request, resource_name="conversation")

    error = apiHelper.check_params(params,
                                   required_params=["token", "sender_id"],
                                   optional_params=["number", "country",
                                                    "recipient_id", "aka",
                                                    "tag"])
    if error != None: return error

    token        = params['token']
    sender_id    = params['sender_id']
    number       = params.get("number")
    country      = params.get("country")
    recipient_id = params.get("recipient_id")
    aka          = params.get("aka")

    if "tag" in params:
        tags = params.getlist("tag")
    else:
        tags = []

    if not session.validate(token):
        return HttpResponseBadRequest("Invalid token")

    user = session.get_user(token)

    # If the caller supplied a phone number and not a recipient ID, try to
    # match the phone number against an existing user.  If the phone number is
    # new, we create a new user for that phone number on-the-fly.

    if number != None and recipient_id == None:
        # Normalize the phone number into E.164 format.

        if country == None: country = "US"

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

        # See if the phone number already exists in the system.

        try:
            recipient_number = UserNumber.objects.get(number=formatted_number)
        except UserNumber.DoesNotExist:
            recipient_number = None

        if recipient_number == None:

            # This is the first time we've encountered this phone number ->
            # create a new User record for this user, and attach it to the
            # phone number.

            recipient_user = User()
            recipient_user.created_at = datetime.datetime.now()
            recipient_user.updated_at = datetime.datetime.now()
            recipient_user.save()

            recipient_number = UserNumber()
            recipient_number.user       = recipient_user
            recipient_number.number     = formatted_number
            recipient_number.verified   = True # Number is already validated.
            recipient_number.created_at = datetime.datetime.now()
            recipient_number.updated_at = datetime.datetime.now()
            recipient_number.save()
        else:
            recipient_user = recipient_number.user

        # We now have a User and UserNumber record for this phone number.
        # Check that we have a profile for that user; if not, we have to create
        # one on the fly.

        profiles = []
        for profile in recipient_user.profile_set.order_by("id"):
            profiles.append(profile)

        if len(profiles) == 0:
            recipient_profile = Profile()
            recipient_profile.user       = recipient_user
            recipient_profile.created_at = datetime.datetime.now()
            recipient_profile.updated_at = datetime.datetime.now()
            recipient_profile.save()
        else:
            recipient_profile = profiles[recipient_user.default_profile]

        # Finally, use the recipient profile for this conversation.

        recipient_id = recipient_profile.id

    else:

        # Check that the caller specified a recipient ID.

        if recipient_id == None:
            return HttpResponseBadRequest("Missing recipient_id parameter")

    # Get the sender and recipient profiles.

    try:
        sender_profile = Profile.objects.get(id=sender_id)
    except Profile.DoesNotExist:
        return HttpResponseBadRequest("Nonexistent sending profile")

    if sender_profile.user != user:
        return HttpResponseBadRequest("sender_id not your profile")

    try:
        recipient_profile = Profile.objects.get(id=recipient_id)
    except Profile.DoesNotExist:
        return HttpResponseBadRequest("Nonexistent recipient profile")

    # See if we already have a conversation for this sender and recipient.

    try:
        conversation = Conversation.objects.get(profile1=sender_profile,
                                                profile2=recipient_profile)
    except Conversation.DoesNotExist:
        try:
            conversation = Conversation.objects.get(profile1=recipient_profile,
                                                    profile2=sender_profile)
        except Conversation.DoesNotExist:
            conversation = None

    if conversation != None:
        # Unhide the existing conversation for both parties.
        conversation.hidden1    = False
        conversation.hidden2    = False
        conversation.updated_at = datetime.datetime.now()
        conversation.save()
    else:
        # There's no existing conversation for these two profiles -> create
        # one.
        conversation = Conversation()
        conversation.profile1   = sender_profile
        conversation.profile2   = recipient_profile
        conversation.hidden1    = False
        conversation.hidden2    = False
        conversation.created_at = datetime.datetime.now()
        conversation.updated_at = datetime.datetime.now()
        conversation.save()

        # If either party has made revelations to the "PUBLIC" profile, copy
        # those revelations and make them directly to the other party.  In this
        # way, changing the public revelations won't affect the revelations
        # made in this conversation.

        _copy_public_revelations(sender_profile, recipient_profile)
        _copy_public_revelations(recipient_profile, sender_profile)

    # Store the "aka" value for this conversation, if one was supplied.

    if aka != None:
        if sender_profile == conversation.profile1:
            conversation.aka1 = aka
        else:
            conversation.aka2 = aka
        conversation.updated_at = datetime.datetime.now()
        conversation.save()

    # If the caller supplied any "tag" values, use these to replace the
    # existing tags (if any).

    if len(tags) > 0:
        ConversationTag.objects.filter(conversation=conversation,
                                       profile=sender_profile).delete()
        for tag in tags:
            conversation_tag = ConversationTag()
            conversation_tag.conversation = conversation
            conversation_tag.profile      = sender_profile
            conversation_tag.tag          = tag
            conversation_tag.created_at   = datetime.datetime.now()
            conversation_tag.updated_at   = datetime.datetime.now()
            conversation_tag.save()

    # Finally, return the conversation back to the caller.

    cdict = conversation.to_dict_for_profile(sender_profile,
                                             include_revelations=True)
    return apiHelper.response({'conversation' : cdict},
                              format=format, status=HTTP_RESPONSE_POST_OK)