Example #1
0
def update_user_task(request, api_call_type, data=None, optin=True, sync=False):
    """Call the update_user task async with the right parameters.

    If sync==True, be sure to do the update synchronously and include the token
    in the response.  Otherwise, basket has the option to do it all later
    in the background.
    """
    from news.tasks import update_user

    sub = getattr(request, 'subscriber', None)
    data = data or request.POST.dict()

    newsletters = data.get('newsletters', None)
    if newsletters:
        if api_call_type == SUBSCRIBE:
            all_newsletters = newsletter_and_group_slugs()
        else:
            all_newsletters = newsletter_slugs()
        for nl in [x.strip() for x in newsletters.split(',')]:
            if nl not in all_newsletters:
                return HttpResponseJSON({
                    'status': 'error',
                    'desc': 'invalid newsletter',
                    'code': errors.BASKET_INVALID_NEWSLETTER,
                }, 400)

    if 'lang' in data:
        if not language_code_is_valid(data['lang']):
            return HttpResponseJSON({
                'status': 'error',
                'desc': 'invalid language',
                'code': errors.BASKET_INVALID_LANGUAGE,
            }, 400)
    elif 'accept_lang' in data:
        lang = get_best_language(get_accept_languages(data['accept_lang']))
        if lang:
            data['lang'] = lang
            del data['accept_lang']
        else:
            return HttpResponseJSON({
                'status': 'error',
                'desc': 'invalid language',
                'code': errors.BASKET_INVALID_LANGUAGE,
            }, 400)

    email = data.get('email', sub.email if sub else None)
    if not email:
        return HttpResponseJSON({
            'status': 'error',
            'desc': MSG_EMAIL_OR_TOKEN_REQUIRED,
            'code': errors.BASKET_USAGE_ERROR,
        }, 400)

    if sync:
        if sub:
            created = False
        else:
            # We need a token for this user. If we don't have a Subscriber
            # object for them already, we'll need to find or make one,
            # checking ET first if need be.
            sub, user_data, created = lookup_subscriber(email=email)

        update_user.delay(data, sub.email, sub.token, api_call_type, optin)
        return HttpResponseJSON({
            'status': 'ok',
            'token': sub.token,
            'created': created,
        })
    else:
        update_user.delay(data, email, None, api_call_type, optin)
        return HttpResponseJSON({
            'status': 'ok',
        })
Example #2
0
def update_user_task(request, api_call_type, data=None, optin=True, sync=False):
    """Call the update_user task async with the right parameters.

    If sync==True, be sure to include the token in the response.
    Otherwise, basket can just do everything in the background.
    """
    data = data or request.POST.dict()

    newsletters = data.get('newsletters', None)
    if newsletters:
        newsletters = [x.strip() for x in newsletters.split(',')]
        if api_call_type == SUBSCRIBE:
            all_newsletters = newsletter_and_group_slugs()
        else:
            all_newsletters = newsletter_slugs()

        private_newsletters = newsletter_private_slugs()

        for nl in newsletters:
            if nl not in all_newsletters:
                return HttpResponseJSON({
                    'status': 'error',
                    'desc': 'invalid newsletter',
                    'code': errors.BASKET_INVALID_NEWSLETTER,
                }, 400)

            if api_call_type != UNSUBSCRIBE and nl in private_newsletters:
                if not request.is_secure():
                    return HttpResponseJSON({
                        'status': 'error',
                        'desc': 'private newsletter subscription requires SSL',
                        'code': errors.BASKET_SSL_REQUIRED,
                    }, 401)

                if not has_valid_api_key(request):
                    return HttpResponseJSON({
                        'status': 'error',
                        'desc': 'private newsletter subscription requires a valid API key',
                        'code': errors.BASKET_AUTH_ERROR,
                    }, 401)

    if 'lang' in data:
        if not language_code_is_valid(data['lang']):
            return HttpResponseJSON({
                'status': 'error',
                'desc': 'invalid language',
                'code': errors.BASKET_INVALID_LANGUAGE,
            }, 400)
    elif 'accept_lang' in data:
        lang = get_best_language(get_accept_languages(data['accept_lang']))
        if lang:
            data['lang'] = lang
            del data['accept_lang']
        else:
            return HttpResponseJSON({
                'status': 'error',
                'desc': 'invalid language',
                'code': errors.BASKET_INVALID_LANGUAGE,
            }, 400)

    email = data.get('email')
    token = data.get('token')
    if not (email or token):
        return HttpResponseJSON({
            'status': 'error',
            'desc': MSG_EMAIL_OR_TOKEN_REQUIRED,
            'code': errors.BASKET_USAGE_ERROR,
        }, 400)

    if sync:
        try:
            user_data, created = get_or_create_user_data(email=email, token=token)
        except NewsletterException as e:
            return newsletter_exception_response(e)

        update_user.delay(data, user_data['email'], user_data['token'], api_call_type, optin,
                          start_time=time())
        return HttpResponseJSON({
            'status': 'ok',
            'token': user_data['token'],
            'created': created,
        })
    else:
        update_user.delay(data, email, token, api_call_type, optin,
                          start_time=time())
        return HttpResponseJSON({
            'status': 'ok',
        })
Example #3
0
 def test_newsletter_and_group_slugs(self):
     self.assertEqual(
         set(newsletters.newsletter_and_group_slugs()),
         {'bowling', 'abiding', 'surfing', 'extorting', 'papers'})
Example #4
0
 def test_newsletter_and_group_slugs(self):
     self.assertEqual(set(newsletters.newsletter_and_group_slugs()),
                      set(['bowling', 'abiding', 'surfing', 'extorting']))
Example #5
0
def update_user_task(request, api_call_type, data=None, optin=False, sync=False):
    """Call the update_user task async with the right parameters.

    If sync==True, be sure to include the token in the response.
    Otherwise, basket can just do everything in the background.
    """
    data = data or request.POST.dict()

    newsletters = parse_newsletters_csv(data.get('newsletters'))
    if newsletters:
        if api_call_type == SUBSCRIBE:
            all_newsletters = newsletter_and_group_slugs() + get_transactional_message_ids()
        else:
            all_newsletters = newsletter_slugs()

        private_newsletters = newsletter_private_slugs()

        for nl in newsletters:
            if nl not in all_newsletters:
                return HttpResponseJSON({
                    'status': 'error',
                    'desc': 'invalid newsletter',
                    'code': errors.BASKET_INVALID_NEWSLETTER,
                }, 400)

            if api_call_type != UNSUBSCRIBE and nl in private_newsletters:
                if not request.is_secure():
                    return HttpResponseJSON({
                        'status': 'error',
                        'desc': 'private newsletter subscription requires SSL',
                        'code': errors.BASKET_SSL_REQUIRED,
                    }, 401)

                if not has_valid_api_key(request):
                    return HttpResponseJSON({
                        'status': 'error',
                        'desc': 'private newsletter subscription requires a valid API key',
                        'code': errors.BASKET_AUTH_ERROR,
                    }, 401)

    if 'lang' in data:
        if not language_code_is_valid(data['lang']):
            data['lang'] = 'en'
    elif 'accept_lang' in data:
        lang = get_best_language(get_accept_languages(data['accept_lang']))
        if lang:
            data['lang'] = lang
            del data['accept_lang']
        else:
            data['lang'] = 'en'

    email = data.get('email')
    token = data.get('token')
    if not (email or token):
        return HttpResponseJSON({
            'status': 'error',
            'desc': MSG_EMAIL_OR_TOKEN_REQUIRED,
            'code': errors.BASKET_USAGE_ERROR,
        }, 400)

    if optin:
        data['optin'] = True

    if api_call_type == SUBSCRIBE and email and data.get('newsletters'):
        # only rate limit here so we don't rate limit errors.
        if is_ratelimited(request, group='news.views.update_user_task.subscribe',
                          key=lambda x, y: '%s-%s' % (data['newsletters'], email),
                          rate=EMAIL_SUBSCRIBE_RATE_LIMIT, increment=True):
            raise Ratelimited()

    if api_call_type == SET and token and data.get('newsletters'):
        # only rate limit here so we don't rate limit errors.
        if is_ratelimited(request, group='news.views.update_user_task.set',
                          key=lambda x, y: '%s-%s' % (data['newsletters'], token),
                          rate=EMAIL_SUBSCRIBE_RATE_LIMIT, increment=True):
            raise Ratelimited()

    if sync:
        statsd.incr('news.views.subscribe.sync')
        if settings.MAINTENANCE_MODE and not settings.MAINTENANCE_READ_ONLY:
            # save what we can
            upsert_user.delay(api_call_type, data, start_time=time())
            # have to error since we can't return a token
            return HttpResponseJSON({
                'status': 'error',
                'desc': 'sync is not available in maintenance mode',
                'code': errors.BASKET_NETWORK_FAILURE,
            }, 400)

        try:
            user_data = get_user_data(email=email, token=token)
        except NewsletterException as e:
            return newsletter_exception_response(e)

        if not user_data:
            if not email:
                # must have email to create a user
                return HttpResponseJSON({
                    'status': 'error',
                    'desc': MSG_EMAIL_OR_TOKEN_REQUIRED,
                    'code': errors.BASKET_USAGE_ERROR,
                }, 400)

        token, created = upsert_contact(api_call_type, data, user_data)
        return HttpResponseJSON({
            'status': 'ok',
            'token': token,
            'created': created,
        })
    else:
        upsert_user.delay(api_call_type, data, start_time=time())
        return HttpResponseJSON({
            'status': 'ok',
        })