Exemplo n.º 1
0
 def ip(self, request):
     """
     Retrieve ip from request
     """
     ip = get_real_ip(request) or 'undefined'
     debug_logger.debug("IP request from : " + ip)
     return Response({'ip': ip})
Exemplo n.º 2
0
def user_from_facebook_auth_response(auth_response, initial_user=None, is_test=False):
    if 'accessToken' in auth_response:
        facebook_access_token = auth_response['accessToken']
    else:
        facebook_access_token = auth_response
    fb_user = fb_user_from_facebook_access_token(facebook_access_token)
    facebook_id = fb_user['id']
    try:
        linked_facebook = LinkedFacebookAccount.objects.filter(facebook_id=facebook_id).select_related(
            'user__profile').first()
        if not linked_facebook:
            raise LinkedFacebookAccount.DoesNotExist()
        save_linked_facebook(linked_facebook.user, facebook_access_token, fb_user, linked_facebook=linked_facebook)
        user = linked_facebook.user
        location = initial_user and initial_user.get('location')
        if location:
            location_controller.update_profile_location(user.ap, location)
    except LinkedFacebookAccount.DoesNotExist:
        debug_logger.debug('LinkedFacebookAccount.DoesNotExist for facebook_id %s' % facebook_id)
        if 'email' not in fb_user:
            dev_msg = 'Facebook user has no email: %s' % json.dumps(fb_user)
            debug_logger.error(dev_msg)
            raise ShoutitBadRequest(message=FB_LINK_ERROR_EMAIL, developer_message=dev_msg)
        user = user_controller.auth_with_facebook(fb_user, initial_user, is_test)
        try:
            save_linked_facebook(user, facebook_access_token, fb_user)
        except (ValidationError, IntegrityError) as e:
            raise ShoutitBadRequest(message=FB_LINK_ERROR_TRY_AGAIN, developer_message=str(e))

    return user
Exemplo n.º 3
0
def auth_with_gplus(gplus_user, credentials, initial_user=None, is_test=False):
    email = gplus_user.get('emails')[0].get('value').lower()
    name = gplus_user.get('name', {})
    first_name = name.get('givenName')
    last_name = name.get('familyName')
    username = initial_user.get('username')
    gplus_id = gplus_user.get('id')
    gender = gplus_user.get('gender')
    profile_fields = {}
    location = {}
    if initial_user:
        if initial_user.get('location'):
            location = initial_user.get('location')
            location_controller.add_predefined_city(location)
        elif initial_user.get('ip'):
            location = location_controller.from_ip(initial_user.get('ip'))
    profile_fields.update(location)
    profile_fields.update({'gender': gender})

    try:
        # Todo: Check!
        # in rare cases when clients send multiple requests and while the first one is still in progress
        # (post save isn't yet completed i.e. no profile yet) the second one passes this check and breaks
        # in the coming lines of updating profile location as there is no profile. The result of such call can be even
        # worse as two users will be created
        user = User.objects.get(email=email)
        debug_logger.debug(
            'Found user: {} with same email of gplus_user: {}'.format(
                user, gplus_id))
        if location:
            location_controller.update_profile_location(user.profile,
                                                        location,
                                                        add_pc=False)
    except User.DoesNotExist:
        user = create_user(email=email,
                           first_name=first_name,
                           last_name=last_name,
                           username=username,
                           is_activated=True,
                           profile_fields=profile_fields,
                           is_test=is_test)

    if not user.is_activated:
        user.activate()

    if not user.profile.gender and gender:
        user.profile.update(gender=gender)

    credentials_json = credentials.to_json()
    try:
        LinkedGoogleAccount.objects.create(user=user,
                                           credentials_json=credentials_json,
                                           gplus_id=gplus_id)
    except IntegrityError as e:
        raise ShoutitBadRequest(
            message=_("Could not access your Google account, try again later"),
            developer_message=str(e))
    image_url = gplus_user['image']['url'].split('?')[0]
    media_controller.set_profile_media(user.profile, 'image', image_url)
    return user
Exemplo n.º 4
0
def _send_welcome_email(user):
    subject = _('Welcome!')
    subs = {'username': user.username}
    if user.is_activated:
        subs.update({
            'text1': "",
            'action': _("Take me to my profile"),
            'link': user.web_url
        })
    else:
        subs.update({
            'text1':
            _("To get started using Shoutit, please activate your account below"
              ),
            'action':
            _("Activate your account"),
            'link':
            user.verification_link
        })
    message = prepare_message(user=user,
                              subject=subject,
                              template=SG_WELCOME_TEMPLATE,
                              subs=subs)
    result = sg.send(message)
    debug_logger.debug("Sent Welcome Email to %s Result: %s" % (user, result))
Exemplo n.º 5
0
def upload_image_to_s3(bucket_name,
                       public_url,
                       url=None,
                       data=None,
                       filename=None,
                       raise_exception=False):
    assert url or data, 'Must pass url or data'
    source = url if url else str(ImageData(data))
    debug_logger.debug("Uploading image to S3 from %s" % source)
    try:
        if not data:
            response = requests.get(url, timeout=10)
            data = response.content
        if not filename:
            filename = generate_image_name()
        # Check if an actual image
        Image.open(StringIO(data))
        # Connect to S3
        s3 = boto3.resource('s3')
        # Upload
        s3.Object(bucket_name, filename).put(
            Body=data, ContentType='image/jpg'
        )  # Todo (mo): set actual content type or convert to jpg
        # Construct public url
        s3_image_url = '%s/%s' % (public_url, filename)
        debug_logger.debug("Uploaded image to S3: %s" % s3_image_url)
        return s3_image_url
    except Exception as e:
        if raise_exception:
            raise e
        else:
            error_logger.warn("Uploading image to S3 failed", exc_info=True)
Exemplo n.º 6
0
def remove_member(channel_name, user_id):
    join = PusherChannelJoin.objects.filter(channel__name=channel_name,
                                            user_id=user_id)
    if join.exists():
        join.delete()
        debug_logger.debug('Removed Member %s from PusherChannel %s' %
                           (user_id, channel_name))
        # Try to delete the channel
        delete_channel(channel_name)
Exemplo n.º 7
0
def auth_with_facebook(fb_user, initial_user=None, is_test=False):
    email = fb_user.get('email').lower()
    first_name = fb_user.get('first_name')
    last_name = fb_user.get('last_name')
    facebook_id = fb_user.get('id')
    gender = fb_user.get('gender')
    birthday = fb_user.get('birthday')
    username = initial_user and initial_user.get('username')
    location = initial_user and initial_user.get('location')
    profile_fields = {}
    update_fields = []
    if location:
        location_controller.add_predefined_city(
            location)  # Todo (mo): are we still using this?
        profile_fields.update(location)
        update_fields += location.keys()
    if gender:
        profile_fields.update({'gender': gender})
        update_fields.append('gender')
    if birthday:
        fmt = "%m/%d/%Y" if birthday.count(
            '/') == 2 else '%d/%m' if birthday.count('/') == 1 else '%Y'
        birthday = datetime.strptime(birthday, fmt).date()
        profile_fields.update({'birthday': birthday})
        update_fields.append('birthday')

    try:
        user = User.objects.filter(
            email=email).select_related('profile').first()
        if not user:
            raise User.DoesNotExist()
        profile = user.profile
        debug_logger.debug('Found user: %s with same email of fb_user: %s' %
                           (user, facebook_id))
        if location:
            location_controller.update_object_location(profile,
                                                       location,
                                                       save=False)
        if gender:
            profile.gender = gender
        profile.save(update_fields=update_fields)

    except User.DoesNotExist:
        user = create_user(email=email,
                           first_name=first_name,
                           last_name=last_name,
                           username=username,
                           is_activated=True,
                           profile_fields=profile_fields,
                           is_test=is_test)

    if not user.is_activated:
        user.activate()

    return user
Exemplo n.º 8
0
def delete_channel(channel_name):
    joins = PusherChannelJoin.objects.filter(channel__name=channel_name)
    if not joins.exists():
        channel = PusherChannel.objects.filter(name=channel_name)
        if channel.exists():
            try:
                channel.delete()
            except IntegrityError:
                debug_logger.debug('Could not delete PusherChannel %s' %
                                   channel_name)
            else:
                debug_logger.debug('Deleted PusherChannel %s' % channel_name)
Exemplo n.º 9
0
def abstract_profile_post_save(sender, instance=None, created=False, **kwargs):
    from shoutit.controllers import notifications_controller
    if not issubclass(sender, AbstractProfile):
        return
    action = 'Created' if created else 'Updated'
    notify = getattr(instance, 'notify', True)
    debug_logger.debug('%s %s: %s | Notify: %s' %
                       (action, instance.model_name, instance, notify))

    if not created:
        if notify:
            # Send `profile_update` notification
            notifications_controller.notify_user_of_profile_update(
                instance.user)
Exemplo n.º 10
0
def create_channel(channel_name):
    if 'presence' in channel_name:
        channel_type = 2
    elif 'private' in channel_name:
        channel_type = 1
    else:
        channel_type = 0

    channel, created = PusherChannel.objects.get_or_create(type=channel_type,
                                                           name=channel_name)
    if created:
        debug_logger.debug('Created PusherChannel %s' % channel_name)
    else:
        debug_logger.debug('PusherChannel %s was already created' %
                           channel_name)
    return channel
Exemplo n.º 11
0
def add_member(channel_name, user_id):
    channel = create_channel(channel_name)
    try:
        join, created = PusherChannelJoin.objects.get_or_create(
            channel=channel, user_id=user_id)
    except IntegrityError:
        # Another call has deleted the channel already
        pass
    else:
        if created:
            debug_logger.debug('Added Member %s to PusherChannel %s' %
                               (user_id, channel.name))
        else:
            debug_logger.debug(
                'Member %s was already added to PusherChannel %s' %
                (user_id, channel.name))
Exemplo n.º 12
0
 def auth(self, request):
     """
     Authorize channel subscriptions.
     ###Not used directly by API clients.
     ---
     """
     user = request.user
     page_admin_user = getattr(request, 'page_admin_user', None)
     authorized = page_admin_user or user
     channel = request.data.get('channel_name', '')
     # Todo: check if the user is allowed to subscribe to the channel
     socket_id = request.data.get('socket_id', '')
     api_version = request.version
     data = {
         'v2': {
             'user_id':
             authorized.pk,
             'user':
             v2_serializers.UserSerializer(authorized,
                                           context={
                                               'request':
                                               create_fake_request('v2')
                                           }).data
         },
         'v3': {
             'user_id':
             authorized.pk,
             'profile':
             v3_serializers.ProfileSerializer(authorized,
                                              context={
                                                  'request':
                                                  create_fake_request('v3')
                                              }).data
         }
     }
     custom_data = data[api_version]
     try:
         auth = pusher.authenticate(channel=channel,
                                    socket_id=socket_id,
                                    custom_data=custom_data)
     except ValueError as e:
         raise ValidationError(str(e))
     debug_logger.debug(
         "Authorized %s to subscribe to %s on %s Pusher on socket_id: %s" %
         (authorized, channel, api_version, socket_id))
     return Response(auth)
Exemplo n.º 13
0
def _send_verified_email(user):
    subject = _('Your email has been verified!')
    subs = {
        'text1':
        _("Thank you for verifying your email. Your account has been verified and you can now use Shoutit "
          "full potential."),
        'action':
        _("Take me to my profile"),
        'link':
        user.web_url
    }
    message = prepare_message(user=user,
                              subject=subject,
                              template=SG_GENERAL_TEMPLATE,
                              subs=subs)
    result = sg.send(message)
    debug_logger.debug("Sent Verified Email to %s Result: %s" % (user, result))
Exemplo n.º 14
0
def _send_password_reset_email(user):
    subject = _('Reset your password')
    subs = {
        'text1':
        _("You have requested to reset your password. If it wasn't you please let us know as soon as possible."
          ),
        'action':
        _("Reset my password"),
        'link':
        user.password_reset_link
    }
    message = prepare_message(user=user,
                              subject=subject,
                              template=SG_GENERAL_TEMPLATE,
                              subs=subs)
    result = sg.send(message)
    debug_logger.debug("Sent Password Reset Email to %s Result: %s" %
                       (user, result))
Exemplo n.º 15
0
def _save_shout_index(shout=None, created=False):
    try:
        if created:
            raise NotFoundError()
        if shout.is_disabled:
            return delete_object_index(ShoutIndex, shout)
        shout_index = ShoutIndex.get(shout.pk)
    except NotFoundError:
        shout_index = ShoutIndex()
        shout_index._id = shout.pk
    shout_index = shout_index_from_shout(shout, shout_index)
    if shout_index.save():
        debug_logger.debug('Created ShoutIndex: %s' % shout.pk)
    else:
        debug_logger.debug('Updated ShoutIndex: %s' % shout.pk)
    # Update the shout without saving the index not to fall in endless loop
    shout.save_shout_index = False
    shout.update(is_indexed=True)
Exemplo n.º 16
0
def _send_verification_email(user):
    subject = _('Verify your email')
    subs = {
        'text1':
        _("Your have changed your email therefore your account is not verified. To "
          "use Shoutit with full potential we need to verify your email."),
        'action':
        _("Verify it now"),
        'link':
        user.verification_link
    }
    message = prepare_message(user=user,
                              subject=subject,
                              template=SG_GENERAL_TEMPLATE,
                              subs=subs)
    result = sg.send(message)
    debug_logger.debug("Sent Verification Email to %s Result: %s" %
                       (user, result))
Exemplo n.º 17
0
def _send_notification_email(user, notification, emailed_for=None):
    from shoutit.controllers import pusher_controller

    # Do nothing if the user is in app (subscribed to Pusher)
    if pusher_controller.check_pusher(user):
        return

    display = notification.display()
    subject = display['title']
    if emailed_for:
        intro = _("Your page '%(page)s' has a new notification") % {
            'page': emailed_for.name
        }
        auth_token = emailed_for.get_valid_auth_token(page_admin_user=user)
    else:
        intro = _("You have a new notification")
        auth_token = user.get_valid_auth_token()
    link = url_with_querystring(notification.web_url, auth_token=auth_token.pk)
    subs = {
        'text1': """
            %(intro)s
            <blockquote style="font-weight:bold;background-color:#EEEEEE;padding:10px;border-radius:5px;">%(text)s</blockquote>
            <p style="font-style:italic;color:#888888;margin-top:50px;">%(note)s</p>
            """ % {
            'intro': force_text(intro),
            'text': force_text(display['text']) or '',
            'note': force_text(display.get('note')) or ''
        },
        'action': display['action'],
        'link': link
    }
    message = prepare_message(user=user,
                              subject=subject,
                              template=SG_GENERAL_TEMPLATE,
                              subs=subs)
    result = sg.send(message)
    debug_logger.debug("Sent Notification Email to %s Result: %s" %
                       (user, result))
Exemplo n.º 18
0
    def filter_queryset(self, request, index_queryset, view):
        user = request.user
        listening = []

        # Listened Tags
        tags = user.listening2_tags_names
        if tags:
            country = user.location.get('country')
            listening_tags = EQ('terms', tags=tags) & EQ('term',
                                                         country=country)
            listening.append(listening_tags)

        # Listened Profiles + user himself
        profiles = [user.pk
                    ] + user.listening2_pages_ids + user.listening2_users_ids
        if profiles:
            listening_profiles = EQ('terms', uid=map(str, profiles))
            listening.append(listening_profiles)

        index_queryset = index_queryset.query('bool', should=listening)
        index_queryset = index_queryset.sort('-published_at')
        debug_logger.debug(index_queryset.to_dict())
        return index_queryset
Exemplo n.º 19
0
    def video_auth(self, request):
        """
        Create a video chat endpoint.
        ###REQUIRES AUTH
        ###Response
        <pre><code>
        {
          "token": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCIsICJjdHkiOiAidHdpbGlvLWZwYTt2PTEifQ.eyJpc3MiOiAiU0s3MDFlYzE",
          "identity": "7c6ca4737db3447f936037374473e61f"
        }
        </code></pre>
        ---
        """
        # Todo: Move the logic to Serializer
        user = request.user
        try:
            video_client = user.video_client

            # Check whether client has an expired token
            if timezone.now() > video_client.expires_at:
                video_client.delete()
                raise ValueError()
        except (AttributeError, ValueError):
            try:
                video_client = create_video_client(user)
            except (ValidationError, IntegrityError) as e:
                msg = _("Couldn't authorize you to make video calls")
                raise ShoutitBadRequest(message=msg,
                                        developer_message=unicode(e))

        # Return token info
        res = OrderedDict([('identity', video_client.identity),
                           ('token', video_client.token),
                           ('expires_at', video_client.expires_at_unix)])
        debug_logger.debug("Authorized %s to use Twilio with identity: %s" %
                           (user, video_client.identity))
        return Response(res)
Exemplo n.º 20
0
    def filter_queryset(self, request, index_queryset, view):
        user = view.get_object()
        data = request.query_params
        listening = []

        # Listened Tags
        tags = user.listening2_tags_names
        if tags:
            country = user.location.get('country')
            listening_tags = Q('terms', tags=tags) & Q('term', country=country)
            listening.append(listening_tags)

        # Listened Profiles + user himself
        users = [user.pk
                 ] + user.listening2_pages_ids + user.listening2_users_ids
        if users:
            listening_users = Q('terms', uid=map(str, users))
            listening.append(listening_users)

        index_queryset = index_queryset.query('bool', should=listening)

        # Sort
        sort = data.get('sort')
        sort_types = {
            None: ('-published_at', ),
            'time': ('-published_at', ),
            'price_asc': ('price', ),
            'price_desc': ('-price', ),
        }
        if sort and sort not in sort_types:
            raise ValidationError({'sort': ["Invalid sort"]})
        # selected_sort = ('-priority',) + sort_types[sort]
        selected_sort = sort_types[sort]
        index_queryset = index_queryset.sort(*selected_sort)

        debug_logger.debug(index_queryset.to_dict())
        return index_queryset
Exemplo n.º 21
0
def user_post_save(sender,
                   instance=None,
                   created=False,
                   update_fields=None,
                   **kwargs):
    from shoutit.controllers import notifications_controller
    action = 'Created' if created else 'Updated'
    is_guest = 'Guest' if instance.is_guest else ''
    notify = getattr(instance, 'notify', True)
    debug_logger.debug('%s %sUser: %s | Notify: %s' %
                       (action, is_guest, instance, notify))

    # Mute / unmute user shouts if his active state was changed
    if isinstance(update_fields, frozenset):
        if 'is_active' in update_fields:
            if instance.is_active:
                instance.un_mute_shouts()
            else:
                instance.mute_shouts()

    if not created:
        if notify:
            # Send notification about user changes
            notifications_controller.notify_user_of_profile_update(instance)
Exemplo n.º 22
0
def publish_shout_to_facebook(shout):
    la = getattr(shout.user, 'linked_facebook', None)
    if not la:
        debug_logger.debug(
            'No linked_facebook, skip publishing Shout %s on Facebook' % shout)
        return
    if 'publish_actions' not in la.scopes:
        debug_logger.debug(
            'No publish_actions in scopes, skip publishing Shout %s on Facebook'
            % shout)
        return
    prod = settings.SHOUTIT_ENV == 'prod'
    namespace = 'shoutitcom' if prod else 'shoutitcom-' + settings.SHOUTIT_ENV
    actions_url = 'https://graph.facebook.com/v2.6/me/%s:shout' % namespace
    params = {
        'access_token': la.access_token,
        shout.get_type_display(): shout.web_url,
        'privacy': "{'value':'EVERYONE'}"
    }
    if prod:
        params['fb:explicitly_shared'] = True
    res = requests.post(actions_url, params=params).json()
    id_on_facebook = res.get('id')
    if id_on_facebook:
        shout.published_on['facebook'] = id_on_facebook
        shout.save(update_fields=['published_on'])
        # Track
        mixpanel_controller.track(shout.user.pk, 'share_shout_on_fb',
                                  shout.track_properties)
        debug_logger.debug('Published shout %s on Facebook' % shout)
    else:
        error_logger.warn('Error publishing shout on Facebook',
                          extra={
                              'res': res,
                              'shout': shout
                          })
Exemplo n.º 23
0
def linked_facebook_account_post_delete(sender, instance, **kwargs):
    debug_logger.debug('Deleted LinkedFacebookAccount for %s' % instance.user)
Exemplo n.º 24
0
    def filter_queryset(self,
                        request,
                        index_queryset,
                        view,
                        extra_query_params=None):
        if not isinstance(index_queryset, Search):
            return index_queryset

        # Copy the query dict to be able to modify it as it is immutable, then update it with extra params
        data = request.query_params.copy()
        if isinstance(extra_query_params, dict):
            data.update(extra_query_params)

        # Update data from discover item shouts query if discover is passed
        discover = data.get('discover')
        if discover:
            try:
                discover_item = DiscoverItem.objects.get(id=discover)
            except ValueError:
                raise InvalidParameter('discover', _("Invalid discover id"))
            except DiscoverItem.DoesNotExist:
                msg = _(
                    "Discover Item with id '%(discover)s' does not exist") % {
                        'discover': discover
                    }
                raise InvalidParameter('discover', msg)
            else:
                data.update(discover_item.shouts_query)

        # Filter shouts by user id if user username is passed in `profile` query param
        user = data.get('profile') or data.get('user')
        if user:
            # Replace `me` with logged in username
            if user == 'me' and request.user.is_authenticated():
                user = request.user.username

            # Get the user id using username
            try:
                user_id = str(
                    User.objects.values('pk').get(username=user)['pk'])
            except User.DoesNotExist:
                msg = _(
                    "Profile with username '%(username)s' does not exist") % {
                        'username': user
                    }
                raise InvalidParameter('profile', msg)
            else:
                index_queryset = index_queryset.filter('term', uid=user_id)

            # When listing user's own shouts show him the expired ones
            if user == request.user.username:
                setattr(view, 'get_expired', True)

        # Exclude shouts using their ids
        exclude = data.get('exclude')
        if isinstance(exclude, basestring):
            exclude = exclude.split(',')
        if exclude and not isinstance(exclude, list):
            exclude = [exclude]
        if exclude:
            index_queryset = index_queryset.filter(
                ~EQ('terms', _id=map(str, exclude)))

        # Shout type
        shout_type = data.get('shout_type')
        if shout_type:
            if shout_type not in ['all', 'offer', 'request']:
                msg = _("Should be `all`, `request` or `offer`")
                raise InvalidParameter('shout_type', msg)
            if shout_type != 'all':
                index_queryset = index_queryset.filter('term', type=shout_type)

        # Search query
        search = data.get('search')
        if search:
            index_queryset = index_queryset.query(
                'multi_match',
                query=search,
                fields=['title', 'text', 'tags'],
                fuzziness='AUTO')

        # Tags
        tags = data.get('tags')
        if tags:
            tags = tags.replace(',', ' ').split()
            tag_names = process_tags(tags)
            index_queryset = index_queryset.filter('terms', tags=tag_names)

        # Location: Country, State, City, Latitude, Longitude
        country = data.get('country', '').upper()
        if country and country != 'all':
            index_queryset = index_queryset.filter('term', country=country)
            # todo: add state
            city = data.get('city')
            if city and city != 'all':
                # todo: use other means of finding the surrounding cities like state.
                try:
                    pd_city = PredefinedCity.objects.filter(city=city,
                                                            country=country)[0]
                except IndexError:
                    pass
                else:
                    nearby_cities = pd_city.get_cities_within(
                        settings.NEARBY_CITIES_RADIUS_KM)
                    cities = map(lambda nc: nc.city, nearby_cities)
                    cities.append(city)
                    cities = arrays.unique(cities)
                    index_queryset = index_queryset.filter('terms',
                                                           city=cities)

        down_left_lat = data.get('down_left_lat')
        down_left_lng = data.get('down_left_lng')
        up_right_lat = data.get('up_right_lat')
        up_right_lng = data.get('up_right_lng')
        latlng_key = ''
        try:
            if down_left_lat:
                latlng_key = 'down_left_lat'
                down_left_lat = float(down_left_lat)
                up_right_lat = up_right_lat or 90
                if down_left_lat > float(up_right_lat) or not (
                        90 >= down_left_lat >= -90):
                    raise InvalidParameter(
                        'down_left_lat',
                        _("Should be between -90 and 90, also not greater than 'up_right_lat'"
                          ))
                index_queryset = index_queryset.filter(
                    'range', **{'latitude': {
                        'gte': down_left_lat
                    }})
            if down_left_lng:
                latlng_key = 'down_left_lng'
                down_left_lng = float(down_left_lng)
                up_right_lng = up_right_lng or 180
                if down_left_lng > float(up_right_lng) or not (
                        180 >= down_left_lng >= -180):
                    raise InvalidParameter(
                        'down_left_lng',
                        _("Should be between -180 and 180, also not greater than 'up_right_lng'"
                          ))
                index_queryset = index_queryset.filter(
                    'range', **{'longitude': {
                        'gte': down_left_lng
                    }})
            if up_right_lat:
                latlng_key = 'up_right_lat'
                if not (90 >= float(up_right_lat) >= -90):
                    raise InvalidParameter('up_right_lat',
                                           _("Should be between -90 and 90"))
                index_queryset = index_queryset.filter(
                    'range', **{'latitude': {
                        'lte': up_right_lat
                    }})
            if up_right_lng:
                latlng_key = 'up_right_lng'
                if not (180 >= float(up_right_lng) >= -180):
                    raise InvalidParameter('up_right_lng',
                                           _("Should be between -180 and 180"))
                index_queryset = index_queryset.filter(
                    'range', **{'longitude': {
                        'lte': up_right_lng
                    }})
        except ValueError:
            raise InvalidParameter(latlng_key, _("Invalid number"))

        # Category and Filters
        category = data.get('category')
        if category and category != 'all':
            try:
                category = Category.objects.prefetch_related('filters').get(
                    slug=category)
            except Category.DoesNotExist:
                msg = _("Category with slug '%(slug)s' does not exist") % {
                    'slug': category
                }
                raise InvalidParameter('category', msg)
            else:
                data['category'] = category.slug
                index_queryset = index_queryset.filter(
                    'terms', category=[category.name, category.slug])
                cat_filters = category.filters.values_list(
                    'slug', 'values_type')
                for cat_f_slug, cat_f_type in cat_filters:
                    if cat_f_type == TAG_TYPE_STR:
                        cat_f_param = data.get(cat_f_slug)
                        if cat_f_param:
                            cat_f_params = cat_f_param.split(',')
                            index_queryset = index_queryset.filter(
                                'terms',
                                **{'filters__%s' % cat_f_slug: cat_f_params})
                    elif cat_f_type == TAG_TYPE_INT:
                        for m1, m2 in [('min', 'gte'), ('max', 'lte')]:
                            cat_f_param = data.get('%s_%s' % (m1, cat_f_slug))
                            if cat_f_param:
                                index_queryset = index_queryset.filter(
                                    'range', **{
                                        'filters__%s' % cat_f_slug: {
                                            m2: cat_f_param
                                        }
                                    })

        # Price
        min_price = data.get('min_price')
        if min_price:
            index_queryset = index_queryset.filter(
                'range', **{'price': {
                    'gte': min_price
                }})

        max_price = data.get('max_price')
        if max_price:
            index_queryset = index_queryset.filter(
                'range', **{'price': {
                    'lte': max_price
                }})

        # Expired
        if not getattr(view, 'get_expired', False):
            now = timezone.now()
            min_published = now - timedelta(days=int(settings.MAX_EXPIRY_DAYS))

            # Recently published and no specified expires_at
            recently_published = EQ('range',
                                    **{'published_at': {
                                        'gte': min_published
                                    }})
            no_expiry_still_valid = EQ(
                'bool',
                filter=[~EQ('exists', field='expires_at'), recently_published])

            # Not expired
            not_expired = EQ('range', **{'expires_at': {'gte': now}})
            expiry_still_valid = EQ(
                'bool', filter=[EQ('exists', field='expires_at'), not_expired])

            index_queryset = index_queryset.filter(no_expiry_still_valid
                                                   | expiry_still_valid)

        # Sorting
        sort = data.get('sort')
        sort_types = {
            None: ('-published_at', ),
            'time': ('-published_at', ),
            'price_asc': ('price', ),
            'price_desc': ('-price', ),
        }
        if sort and sort not in sort_types:
            raise InvalidParameter('sort', _("Invalid sort"))
        # selected_sort = ('-priority',) + sort_types[sort]
        selected_sort = sort_types[sort]
        if search:
            selected_sort = ('_score', ) + selected_sort
        index_queryset = index_queryset.sort(*selected_sort)

        debug_logger.debug(index_queryset.to_dict())
        index_queryset.search_data = {
            k: parse_int(v, 10) or v
            for k, v in data.items()
        }
        return index_queryset
Exemplo n.º 25
0
    def filter_queryset(self,
                        request,
                        index_queryset,
                        view,
                        extra_query_params=None):
        if not isinstance(index_queryset, Search):
            return index_queryset

        # Copy the query dict to be able to modify it as it is immutable, then update it with extra params
        data = request.query_params.copy()
        if isinstance(extra_query_params, dict):
            data.update(extra_query_params)

        # Update data from discover item shouts query if discover is passed
        discover = data.get('discover')
        if discover:
            try:
                discover_item = DiscoverItem.objects.get(id=discover)
            except DiscoverItem.DoesNotExist:
                raise ValidationError({
                    'discover':
                    ["Discover Item with id '%s' does not exist" % discover]
                })
            else:
                data.update(discover_item.shouts_query)

        # Filter shouts by user id if user username or id are passed in `user` query param
        user = data.get('user')
        if user:
            try:
                user_id = User.objects.get(username=user).pk
            except User.DoesNotExist:
                raise ValidationError({
                    'user': ["User with username '%s' does not exist" % user]
                })
            else:
                index_queryset = index_queryset.filter('term', uid=user_id)

        # Exclude ids
        exclude_ids = data.get('exclude_ids')
        if isinstance(exclude_ids, basestring):
            exclude_ids = exclude_ids.split(',')
        if exclude_ids and not isinstance(exclude_ids, list):
            exclude_ids = [exclude_ids]
        if exclude_ids:
            index_queryset = index_queryset.filter(
                ~Q('terms', _id=map(str, exclude_ids)))

        # Shout type
        shout_type = data.get('shout_type')
        if shout_type:
            if shout_type not in ['all', 'offer', 'request']:
                raise ValidationError(
                    {'shout_type': ["Should be `all`, `request` or `offer`"]})
            if shout_type != 'all':
                index_queryset = index_queryset.filter('term', type=shout_type)

        # Search query
        search = data.get('search')
        if search:
            index_queryset = index_queryset.query(
                'multi_match',
                query=search,
                fields=['title', 'text', 'tags'],
                fuzziness='AUTO')

        # Tags
        tags = data.get('tags')
        if tags:
            tags = tags.replace(',', ' ').split()
            tag_names = process_tags(tags)
            index_queryset = index_queryset.filter('terms', tags=tag_names)

        # Location: Country, State, City, Latitude, Longitude
        country = data.get('country', '').upper()
        if country and country != 'all':
            index_queryset = index_queryset.filter('term', country=country)
            # todo: add state
            city = data.get('city')
            if city and city != 'all':
                # todo: use other means of finding the surrounding cities like state.
                try:
                    pd_city = PredefinedCity.objects.filter(city=city,
                                                            country=country)[0]
                except IndexError:
                    pass
                else:
                    nearby_cities = pd_city.get_cities_within(
                        settings.NEARBY_CITIES_RADIUS_KM)
                    cities = map(lambda nc: nc.city, nearby_cities)
                    cities.append(city)
                    cities = arrays.unique(cities)
                    index_queryset = index_queryset.filter('terms',
                                                           city=cities)

        latlng_errors = OrderedDict()
        down_left_lat = data.get('down_left_lat')
        down_left_lng = data.get('down_left_lng')
        up_right_lat = data.get('up_right_lat')
        up_right_lng = data.get('up_right_lng')
        try:
            if down_left_lat:
                down_left_lat = float(down_left_lat)
                if down_left_lat > float(up_right_lat) or not (
                        90 >= down_left_lat >= -90):
                    latlng_errors['down_left_lat'] = [
                        "should be between -90 and 90, also not greater than 'up_right_lat'"
                    ]
                    index_queryset = index_queryset.filter(
                        'range', **{'latitude': {
                            'gte': down_left_lat
                        }})
            if down_left_lng:
                down_left_lng = float(down_left_lng)
                if down_left_lng > float(up_right_lng) or not (
                        180 >= down_left_lng >= -180):
                    latlng_errors['down_left_lng'] = [
                        "should be between -180 and 180, also not greater than 'up_right_lng'"
                    ]
                index_queryset = index_queryset.filter(
                    'range', **{'longitude': {
                        'gte': down_left_lng
                    }})
            if up_right_lat:
                if not (90 >= float(up_right_lat) >= -90):
                    latlng_errors['up_right_lat'] = [
                        "should be between -90 and 90"
                    ]
                index_queryset = index_queryset.filter(
                    'range', **{'latitude': {
                        'lte': up_right_lat
                    }})
            if up_right_lng:
                if not (180 >= float(up_right_lng) >= -180):
                    latlng_errors['up_right_lng'] = [
                        "should be between -180 and 180"
                    ]
                index_queryset = index_queryset.filter(
                    'range', **{'longitude': {
                        'lte': up_right_lng
                    }})
        except ValueError:
            latlng_errors['error'] = ["invalid lat or lng parameters"]
        if latlng_errors:
            raise ValidationError(latlng_errors)

        # Category and Filters
        category = data.get('category')
        if category and category != 'all':
            try:
                category = Category.objects.prefetch_related('filters').get(
                    DQ(name=category) | DQ(slug=category))
            except Category.DoesNotExist:
                raise ValidationError({
                    'category': [
                        "Category with name or slug '%s' does not exist" %
                        category
                    ]
                })
            else:
                data['category'] = category.slug
                index_queryset = index_queryset.filter(
                    'terms', category=[category.name, category.slug])
                cat_filters = category.filters.values_list(
                    'slug', 'values_type')
                for cat_f_slug, cat_f_type in cat_filters:
                    if cat_f_type == TAG_TYPE_STR:
                        cat_f_param = data.get(cat_f_slug)
                        if cat_f_param:
                            index_queryset = index_queryset.filter(
                                'term',
                                **{'filters__%s' % cat_f_slug: cat_f_param})
                    elif cat_f_type == TAG_TYPE_INT:
                        for m1, m2 in [('min', 'gte'), ('max', 'lte')]:
                            cat_f_param = data.get('%s_%s' % (m1, cat_f_slug))
                            if cat_f_param:
                                index_queryset = index_queryset.filter(
                                    'range', **{
                                        'filters__%s' % cat_f_slug: {
                                            m2: cat_f_param
                                        }
                                    })

        # Price
        min_price = data.get('min_price')
        if min_price:
            index_queryset = index_queryset.filter(
                'range', **{'price': {
                    'gte': min_price
                }})

        max_price = data.get('max_price')
        if max_price:
            index_queryset = index_queryset.filter(
                'range', **{'price': {
                    'lte': max_price
                }})

        # Sorting
        sort = data.get('sort')
        sort_types = {
            None: ('-published_at', ),
            'time': ('-published_at', ),
            'price_asc': ('price', ),
            'price_desc': ('-price', ),
        }
        if sort and sort not in sort_types:
            raise ValidationError({'sort': ["Invalid sort"]})
        # selected_sort = ('-priority',) + sort_types[sort]
        selected_sort = sort_types[sort]
        if search:
            selected_sort = ('_score', ) + selected_sort
        index_queryset = index_queryset.sort(*selected_sort)

        debug_logger.debug(index_queryset.to_dict())
        index_queryset.search_data = {
            k: parse_int(v, 10) or v
            for k, v in data.items()
        }
        return index_queryset
Exemplo n.º 26
0
 def delete_apns_devices(self):
     APNSDevice.objects.filter(user=self).delete()
     debug_logger.debug("Deleted APNSDevices for %s" % self)
Exemplo n.º 27
0
 def delete_gcm_devices(self):
     GCMDevice.objects.filter(user=self).delete()
     debug_logger.debug("Deleted GCMDevices for %s" % self)
Exemplo n.º 28
0
def _subscribe_users_to_mailing_list(users=None,
                                     user_ids=None,
                                     raise_errors=True):
    if users is None:
        users = User.objects.filter(id__in=user_ids)
    request_body = []
    for user in users:
        ap = user.ap
        fields = {
            'email':
            user.email,
            'first_name':
            user.first_name,
            'last_name':
            user.last_name,
            'is_active':
            'true' if user.is_active else 'false',
            'is_activated':
            'true' if user.is_activated else 'false',
            'type':
            user.v3_type_name,
            'username':
            user.username,
            'date_joined':
            date_unix(user.date_joined),
            'last_login':
            date_unix(user.last_login) if user.last_login else 0,
            'country':
            ap.country,
            'image':
            ap.image,
            'platform':
            " ".join(
                map(lambda c: str(c.replace('shoutit-', '')),
                    user.api_client_names)),
            'gender':
            getattr(ap, 'gender', ''),
        }
        request_body.append(fields)
    try:
        response = sg_api.client.contactdb.recipients.post(
            request_body=request_body)
        response_data = json.loads(response.response_body)

        # Check added
        if response_data['new_count'] > 0:
            debug_logger.debug("Added %d user(s) to SendGrid Contacts DB" %
                               response_data['new_count'])
        # Check updated
        if response_data['updated_count'] > 0:
            debug_logger.debug("Updated %d user(s) on SendGrid Contacts DB" %
                               response_data['updated_count'])

        # Update added / updated users
        added_emails = map(lambda pr: base64.b64decode(pr),
                           response_data['persisted_recipients'])
        User.objects.filter(email__in=added_emails).update(
            on_mailing_list=True)

        # Errors
        if response_data['error_count'] > 0:
            debug_logger.warning(
                "Error adding/updating %d user(s) to SendGrid contacts db" %
                response_data['error_count'])
            debug_logger.warning(response_data['errors'])
            raise ValueError(response_data['errors'])
    except Exception as e:
        debug_logger.warning("Error adding/updating %d users to SendGrid: %s" %
                             (len(users), str(e)))
        if raise_errors:
            raise
Exemplo n.º 29
0
def linked_facebook_account_post_save(sender, instance, created, **kwargs):
    action = 'Created' if created else 'Updated'
    debug_logger.debug('%s LinkedFacebookAccount for %s' %
                       (action, instance.user))
Exemplo n.º 30
0
    def handle(self, *args, **options):

        users = list(User.objects.filter(username__startswith='test_100'))
        categories = list(Category.objects.all())
        cities = PredefinedCity.objects.all()

        # adding test users if we don't have them
        if not len(users) == self.max_users:
            for i in range(self.max_users):
                username = '******' + str(1000000 + i)
                email = username + '@shoutit.com'
                user, created = User.objects.get_or_create(username=username,
                                                           first_name='User',
                                                           last_name=username,
                                                           email=email,
                                                           is_test=True)
                if created:
                    profile = user.profile
                    city = random.choice(cities)
                    profile.city = city.city
                    profile.country = city.country
                    profile.latitude = city.latitude + random.uniform(
                        -3, 3) / 100.0
                    profile.longitude = city.longitude + random.uniform(
                        -3, 3) / 100.0
                    profile.save()
                debug_logger.debug(
                    'Created test user in: {}, lat: {}, lng: {}'.format(
                        user.profile.city, user.profile.latitude,
                        user.profile.longitude))
                users.append(user)

        for i in range(
                min(max(options.get('num_shouts')[0], self.min_shouts),
                    self.max_shouts)):
            user = random.choice(users)
            type = random.choice(['offer', 'request'])
            category = random.choice(categories)
            city = random.choice(cities)
            tags = Tag.objects.filter(key__categories=category).values_list(
                'slug', flat=True)
            tags = ['filling-shout'] + random.sample(
                tags, random.randint(0, min(5, len(tags))))
            self.stdout.write(str(tags))
            images = [
                "https://shout-image.static.shoutit.com/opo0928a.jpg",
                "https://shout-image.static.shoutit.com/heic1501a.jpg",
                "https://shout-image.static.shoutit.com/heic0702a.jpg"
            ]
            random.shuffle(images)
            shout_data = {
                "type":
                type,
                "title":
                "{0} {1} in {2} at {3:0.0f}".format(category.name, type,
                                                    city.city, time.time()),
                "text":
                " ".join(tags),
                "price":
                random.randint(0, 1000),
                "currency":
                "EUR",
                "images":
                images,
                "category": {
                    "name": category.name
                },
                "tags": [{
                    'name': t
                } for t in tags],
                "location": {
                    "country": city.country,
                    "city": city.city,
                    "latitude": city.latitude + random.uniform(-4, 3) / 100.0,
                    "longitude": city.longitude + random.uniform(-4, 3) / 100.0
                }
            }
            request = create_fake_request('v2')
            request._user = user
            shout = ShoutDetailSerializer(data=shout_data,
                                          context={'request': request})
            shout.is_valid(True)
            shout.save()

        self.stdout.write('Successfully filled shouts')