示例#1
0
def restart(session, topic_id, other_user_id):
    """ Restart a stopped conversation.
    """
    raise UnauthorizedException() # Disable for now.

    if session == None or topic_id == None or other_user_id == None:
        raise InvalidParametersException()

    sessionHandler.validate(session)
    user = sessionHandler.get_user(session)

    try:
        topic = Topic.objects.get(id=topic_id)
    except Topic.DoesNotExist:
        raise NoSuchTopicException()

    try:
        other_user = User.objects.get(id=other_user_id)
    except User.DoesNotExist:
        raise NoSuchUserException()

    conversation = conversationHandler.get(user.id, other_user.id, topic.id)

    conversationHandler.send_to_both_parties(
        conversation, settings.SMS_TEXT_CONVERSATION_RESTARTING)

    conversation.stopped = False
    conversation.save()
示例#2
0
def update(session, photo=None, name=None, email=None, website=None,
           location=None, bio=None):
    """ Update the user profile for the currently logged-in user.
    """
    raise UnauthorizedException() # Disable for now.

    # Check that the session is still valid.

    try:
        if session == None:
            raise InvalidParametersException()

        sessionHandler.validate(session)
        user = sessionHandler.get_user(session)

        # Log into the 3taps Identity API.

        success,response = identity_api.login(username=user.username,
                                              pass_hash=user.identity_api_hash)
        if not success:
            print "No 3taps identity!"
            return {} # No 3taps identity -> can't update the profile.

        session = response

        # Update the user's profile.

        changes = {}
        if photo    != None: changes['photo']    = photo
        if name     != None: changes['name']     = name
        if email    != None: changes['email']    = email
        if website  != None: changes['website']  = website
        if location != None: changes['location'] = location
        if bio      != None: changes['bio']      = bio

        success,response = identity_api.update(session, changes)
        if not success:
            print "Internal server error with Identity API!"
            print response
            return {}

        updated_profile = response['profile']

        # Finally, log out again and return the updated profile back to the
        # caller.

        identity_api.logout(session)
        return updated_profile
    except:
        traceback.print_exc()
        raise
示例#3
0
文件: topics.py 项目: 3taps/MessageMe
def update(session, topic_id, name=None, active=None, hide_username=None):
    """ Update the details of the given topic.
    """
    raise UnauthorizedException() # Disable for now.

    if session == None:
        raise InvalidParametersException()

    sessionHandler.validate(session)

    user = sessionHandler.get_user(session)

    try:
        topic = Topic.objects.get(id=topic_id)
    except Topic.DoesNotExist:
        raise NoSuchTopicException()

    if topic.user != user:
        raise UnauthorizedException()

    # Update the topic name, if we've been asked to do so.

    if name not in ["", None]:
        _check_topic_name(name)

        try:
            existing_topic = Topic.objects.get(user=user, name=name)
        except Topic.DoesNotExist:
            existing_topic = None

        if existing_topic != None and topic.id != existing_topic.id:
            raise DuplicateTopicNameException()

        topic.name = name

    # Update the 'active' flag, if we've been asked to do so.

    if active != None:
        topic.active = (active in [1, "1", "true", "True", True])

    # Update the 'hide_username' flag, if we've been asked to do so.

    if hide_username != None:
        topic.hide_username = (hide_username in [1, "1", "true", "True", True])

    # Finally, save the updated topic, and return a copy of it back to the
    # caller.

    topic.save()
    return topic.to_dict()
示例#4
0
文件: users.py 项目: 3taps/MessageMe
def get(session):
    """ Retrieve the user dictionary for the currently logged-in user.
    """
    raise UnauthorizedException() # Disable for now.

    logger.debug("in core.api.users.get(" +
                 "session=%s)" % repr(session))

    if session == None:
        raise InvalidParametersException()

    sessionHandler.validate(session)

    return sessionHandler.get_user(session).to_dict()
示例#5
0
def send(session, topic_id, sender_name=None, message=None):
    """ Send a message.
    """
    raise UnauthorizedException() # Disable for now.

    logger.debug("core.api.messages.send(" +
                 'session=%s, topic_id=%s, sender_name=%s, message=%s)'
                 % (repr(session), repr(topic_id), repr(sender_name),
                    repr(message)))

    try:
        if session == None or topic_id == None or message == None:
            raise InvalidParametersException()

        sessionHandler.validate(session)

        sender = sessionHandler.get_user(session)

        try:
            topic = Topic.objects.get(id=topic_id)
        except Topic.DoesNotExist:
            raise NoSuchTopicException()

        if not topic.active:
            raise InactiveTopicException()

        recipient    = topic.user
        phone_number = recipient.phone_number

        rateLimiter.ensure_phone_number_below_rate_limit(phone_number)

        if messageHandler.handle_special_message(sender, recipient, topic,
                                                 message):
            msg = None
        else:
            msg = messageHandler.send_message(sender, recipient, topic,
                                              sender_name, message)
            rateLimiter.sms_message_sent_to(phone_number)

        if msg != None:
            return msg.to_dict()
        else:
            return None
    except RateLimitReachedException:
        raise
    except:
        traceback.print_exc()
        raise
示例#6
0
文件: topics.py 项目: 3taps/MessageMe
def list(session):
    """ Return a list of the topics owned by the currently logged-in user.
    """
    raise UnauthorizedException() # Disable for now.

    if session == None:
        raise InvalidParametersException()

    sessionHandler.validate(session)

    user = sessionHandler.get_user(session)

    topic_dicts = []
    for topic in Topic.objects.filter(user=user).order_by("id"):
        topic_dicts.append(topic.to_dict())
    return topic_dicts
示例#7
0
文件: users.py 项目: 3taps/MessageMe
def verify_user_owns_number(session, phone_number, verification_code):
    """ Verify that the currently logged-in user owns the given phone number.
    """
    raise UnauthorizedException() # Disable for now.

    logger.debug("in core.api.users.verify_user_owns_number(" +
                 "session=%s, phone_number=%s, verification_code=%s)" %
                 (repr(session), repr(phone_number), repr(verification_code)))

    if session == None or phone_number == None or verification_code == None:
        raise InvalidParametersException()

    sessionHandler.validate(session)
    user = sessionHandler.get_user(session)

    phone_number = utils.format_phone_number(phone_number)

    try:
        user_with_phone = User.objects.get(phone_number=phone_number)
    except User.DoesNotExist:
        user_with_phone = None

    if user_with_phone == None:
        raise NoSuchPhoneNumberException()

    if verification_code != user_with_phone.verification_code:
        raise UnauthorizedException()

    if user == user_with_phone:
        # The user already has this phone number.  Simply verify it.
        user.verified = True
        user.save()
        return

    # If we get here, the phone number was originally owned by someone else.
    # Transfer the phone number over to the currently logged-in user.

    user.phone_number      = user_with_phone.phone_number
    user.verification_code = user_with_phone.verification_code
    user.verified          = True
    user.save()

    user_with_phone.phone_number      = None
    user_with_phone.verification_code = None
    user_with_phone.verified          = False
    user_with_phone.save()
示例#8
0
文件: users.py 项目: 3taps/MessageMe
def delete(session):
    """ Delete the currently logged-in user.

        Note that we don't currently delete the user from the 3taps Identity
        API.  This may change in the future.
    """
    raise UnauthorizedException() # Disable for now.

    logger.debug("in core.api.users.delete(" +
                 "session=%s)" % repr(session))

    if session == None:
        raise InvalidParametersException()

    sessionHandler.validate(session)
    user = sessionHandler.get_user(session)
    sessionHandler.delete(session)

    user.delete()
示例#9
0
文件: topics.py 项目: 3taps/MessageMe
def create(session, topic_name=None):
    """ Create a new topic for the currently logged-in user.
    """
    raise UnauthorizedException() # Disable for now.

    if session == None:
        raise InvalidParametersException()

    sessionHandler.validate(session)

    user = sessionHandler.get_user(session)

    if topic_name == "": topic_name = None

    if topic_name == None:
        # Create a new random name for this topic.
        while True:
            topic_name = utils.random_letters_and_digits(min_length=4,
                                                         max_length=6)
            if not Topic.objects.filter(user=user,name=topic_name).exists():
                break

    _check_topic_name(topic_name)

    try:
        existing_topic = Topic.objects.get(user=user, name=topic_name)
    except Topic.DoesNotExist:
        existing_topic = None

    if existing_topic != None:
        raise DuplicateTopicNameException()

    topic = Topic()
    topic.user          = user
    topic.name          = topic_name
    topic.active        = True
    topic.num_views     = 0
    topic.hide_username = False
    topic.hidden_url    = hiddenURLs.generate(user) # URL for user, not topic.
    topic.save()

    return topic.to_dict()
示例#10
0
def get(session):
    """ Return the user profile for the currently logged-in user.
    """
    raise UnauthorizedException() # Disable for now.

    # Check that the session is still valid.

    if session == None:
        raise InvalidParametersException()

    sessionHandler.validate(session)
    user = sessionHandler.get_user(session)

    # Log in to the 3taps identity API.

    success,response = identity_api.login(username=user.username,
                                          pass_hash=user.identity_api_hash)
    if not success:
        print "No 3taps identity!"
        return {} # No 3taps identity -> return an empty profile.

    session = response

    # Get the user's details, and extract the profile.

    success,response = identity_api.get_user(session)
    if not success:
        print "Should never happen!"
        print response
        return {} # Should never happen.

    profile = response['profile']

    # Finally, log out from the identity API again, and return the profile back
    # to the caller.

    identity_api.logout(session)
    return profile
示例#11
0
文件: users.py 项目: 3taps/MessageMe
def merge(old_session, new_session):
    """ Merge two users.
    """
    raise UnauthorizedException() # Disable for now.

    logger.debug("in core.api.users.merge(" +
                 "old_session=%s, new_session=%s)" %
                 (repr(old_session), repr(new_session)))

    # Check that the session parameters are correct.  We require two valid
    # session IDs, the old one for an ad hoc user, and the new one for a non-ad
    # hoc user.

    if old_session == None or new_session == None:
        raise InvalidParametersException()

    sessionHandler.validate(old_session)
    sessionHandler.validate(new_session)

    old_user = sessionHandler.get_user(old_session)
    new_user = sessionHandler.get_user(new_session)

    if not old_user.ad_hoc or new_user.ad_hoc:
        raise UnauthorizedException()

    # Build a list of the old user's conversations.

    old_conversations = []
    for conversation in Conversation.objects.filter(user_1=old_user):
        old_conversations.append(conversation)
    for conversation in Conversation.objects.filter(user_2=old_user):
        if conversation.user_1 != old_user:
            old_conversations.append(conversation)

    # Build a list of the old user's active conversations.  Note that we only
    # store the ID of the other user and the topic ID for the conversation, as
    # the Conversation object itself may get deleted as part of the merge
    # process.  We'll need this to send an SMS to the new user telling them
    # that they've taken the conversation mobile.

    active_conversations = [] # List of (other_user_id, topic_id) tuples.
    for conversation in Conversation.objects.filter(user_1=old_user):
        if not conversation.stopped:
            active_conversations.append((conversation.user_2.id,
                                         conversation.topic.id))
    for conversation in Conversation.objects.filter(user_2=old_user):
        if not conversation.stopped and conversation.user_1 != old_user:
            active_conversations.append((conversation.user_1.id,
                                         conversation.topic.id))

    # Build a list of the new user's conversations.

    new_conversations = []
    for conversation in Conversation.objects.filter(user_1=new_user):
        new_conversations.append(conversation)
    for conversation in Conversation.objects.filter(user_2=new_user):
        if conversation.user_1 == new_user:
            new_conversations.append(conversation)

    # Change each of the old conversations to belong to the new user.  If the
    # updated conversation is a duplicate of an existing conversation for the
    # new user, we have to delete the old conversation and update the
    # associated messages.

    for old_conversation in old_conversations:
        if old_conversation.user_1 == old_user:
            other_old_user = old_conversation.user_2
        else:
            other_old_user = old_conversation.user_1

        is_duplicate = False
        for new_conversation in new_conversations:
            if new_conversation.user_1 == new_user:
                other_new_user = new_conversation.user_2
            else:
                other_new_user = new_conversation.user_1

            if other_old_user == other_new_user:
                is_duplicate = True
                break

        if is_duplicate:
            # Update the messages for old_conversation to be part of the
            # new_conversation instead, and delete the old conversation.
            Message.objects.filter(conversation=old_conversation).update(
                                            conversation=new_conversation)
            old_conversation.delete()
        else:
            # Change the old_conversation to belong to the new_user instead of
            # the old_user.
            if old_conversation.user_1 == old_user:
                old_conversation.user_1 = new_user
            else:
                old_conversation.user_2 = new_user
            old_conversation.save()

    # Update the old user's messages to refer to the new user.

    Message.objects.filter(sender=old_user).update(sender=new_user)

    # Update any topics owned by the old user to now be owned by the new user.
    # Note that we deliberately avoid overwriting the default and any existing
    # named topics for the new user.

    topics = []
    for topic in Topic.objects.filter(user=old_user):
        topics.append(topic)

    for topic in topics:
        if topic.default:
            continue # Don't copy across default topic.
        if Topic.objects.filter(user=new_user, name=topic.name):
            continue # Don't overwrite existing named topic.
        topic.user = new_user
        topic.save()

    # Update any SMS channels which sent messages to the old user to now send
    # messages to the new user.

    channels = []
    for channel in TwilioSMSChannel.objects.filter(sender=old_user):
        channels.append(channel)

    for channel in channels:
        if TwilioSMSChannel.objects.filter(conversation=channel.conversation,
                                           recipient=channel.recipient,
                                           phone_number=channel.phone_number,
                                           sender=new_user).exists():
            continue # Don't overwrite existing SMS channel.
        channel.sender = new_user
        channel.save()

    # Update any SMS channels which sent messages from the old user to now send
    # messages from the new user.

    channels = []
    for channel in TwilioSMSChannel.objects.filter(recipient=old_user):
        channels.append(channel)

    for channel in channels:
        if TwilioSMSChannel.objects.filter(conversation=channel.conversation,
                                           sender=channel.sender,
                                           phone_number=channel.phone_number,
                                           recipient=new_user).exists():
            continue # Don't overwrite existing SMS channel.
        channel.recipient = new_user
        channel.save()

    # Finally, if the new user has a verified phone number, send a message to
    # the new user for each active conversation, telling the user that they
    # have "taken the conversation mobile."

    if new_user.verified:
        for other_user,topic in active_conversations:
            try:
                conversation = Conversation.objects.get(user_1=new_user,
                                                        user_2__id=other_user,
                                                        topic=topic)
            except Conversation.DoesNotExist:
                conversation = Conversation.objects.get(user_1__id=other_user,
                                                        user_2=new_user,
                                                        topic=topic)

            sending_phone_number = twilio_gateway.calc_sending_phone_number(
                                                    conversation, new_user)
            msg = settings.SMS_TEXT_CONVERSATION_TAKEN_MOBILE
            twilio_gateway.send_sms(sending_phone_number,
                                    new_user.phone_number, msg)
示例#12
0
文件: users.py 项目: 3taps/MessageMe
def update(session, username=None, password=None, phone_number=None):
    """ Update the details of the currently logged-in user.
    """
    raise UnauthorizedException() # Disable for now.

    logger.debug("in core.api.users.update(" +
                 "session=%s, username=%s, password=%s, phone_number=%s)" %
                 (repr(session), repr(username), repr(password),
                  repr(phone_number)))

    if session == None:
        raise InvalidParametersException()

    sessionHandler.validate(session)
    user = sessionHandler.get_user(session)

    # Remember if the user had a username or password.

    if user.username not in ["", None]:
        had_username = True
    else:
        had_username = False

    if user.password_salt not in ["", None]:
        had_password = True
    else:
        had_password = False

    # If we're setting a username and password for this user, and we didn't
    # have one previously, create a 3taps Identity for this user.  Note that
    # this may fail, if the username is already in use.

    if not had_username and username != None:
        if password == None: raise InvalidParametersException()
        _check_username(username)
        _check_password(password)

        # Try creating this user within the 3taps Identity API.

        success,response = identity_api.create(username, password)
        if not success:
            if response.startswith("403 error"):
                raise DuplicateUsernameException()
            else:
                raise InvalidParametersException()

        # Check that we don't have a local user with that username.

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

        if existing_user != None:
            raise DuplicateUsernameException()

        # Finally, save the updated user details into our database.

        salt = response['server_salt']
        hash = hashlib.md5(password + salt).hexdigest()

        user.uses_identity_api = True
        user.username          = username
        user.identity_api_salt = salt
        user.identity_api_hash = hash
        user.save()

    # If we're changing the username for this user, ask the 3taps Identity API
    # to change the username.  Note that this may fail, if the new username is
    # already in use.

    if had_username and username != None and username != user.username:
        success,response = identity_api.login(user.username,
                                              pass_hash=user.identity_api_hash)
        if not success:
            raise UnauthorizedException()

        session = response

        success,response = identity_api.update(session,
                                               {'username' : username})
        if not success:
            if response.startswith("403 error"):
                raise DuplicateUsernameException()
            else:
                raise InvalidParametersException()

        identity_api.logout(session)

        # Check that we don't have a local user with that username.

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

        if existing_user != None:
            raise DuplicateUsernameException()

        # Finally, save the updated user details into our database.

        user.username = username
        user.save()

    # If we're changing the password for this user, ask the 3taps Identity API
    # to change the password.

    if password != None:
        if user.username in ["", None]:
            # We can't change the password if we don't have a username.
            raise InvalidParametersException()

        if user.uses_identity_api:
            success,response = \
                    identity_api.login(user.username,
                                       pass_hash=user.identity_api_hash)
        else:
            success,response = \
                    identity_api.login(user.username,
                                       password="******")

        if not success:
            raise UnauthorizedException()

        session = response

        success,response = identity_api.update(session,
                                               {'username' : username})
        if not success:
            if response.startswith("403 error"):
                raise DuplicateUsernameException()
            else:
                raise InvalidParametersException()

        identity_api.logout(session)

        salt = response['server_salt']
        hash = hashlib.md5(password + salt).hexdigest()

        user.uses_identity_api = True
        user.identity_api_salt = salt
        user.identity_api_hash = hash
        user.save()

    # If we've been asked to update the user's phone number, do so.

    # NOTE: someone was using this to hack our system, so I've disabled it.

    if False: # phone_number != None:
        if phone_number == "":
            user.phone_number = None # Remove current phone number.
        else:
            phone_number = utils.format_phone_number(phone_number)

            try:
                existing_user = User.objects.get(phone_number=phone_number)
            except User.DoesNotExist:
                existing_user = None

            if existing_user != None and user.id != existing_user.id:
                raise DuplicatePhoneNumberException()

        user.phone_number = phone_number

    # If this was an ad hoc user who we're now making permanent, change their
    # "ad hoc" status, and create a new default topic for the user.

    if user.ad_hoc and (username != None or password != None or
                        phone_number != None):
        user.ad_hoc = False
        _create_default_topic(user)

    # If we have been given a username and password for this user, record them
    # as signing up.

    if not had_username and not had_password:
        if username not in ["", None] and password not in ["", None]:
            eventRecorder.record_event(eventRecorder.EVENT_TYPE_NEW_USER_SIGNUP)

    # Finally, save the updated user and return a copy of it back to the
    # caller.

    user.updated_at = datetime.datetime.utcnow()
    user.save()

    return user.to_dict()