Exemple #1
0
def subscribe_main(request):
    """Subscription view for use with client side JS"""
    form = SubscribeForm(request.POST)
    if form.is_valid():
        data = form.cleaned_data

        if email_is_blocked(data['email']):
            statsd.incr('news.views.subscribe_main.email_blocked')
            # don't let on there's a problem
            return respond_ok(request, data)

        data['format'] = data.pop('fmt') or 'H'

        if data['lang']:
            if not language_code_is_valid(data['lang']):
                data['lang'] = 'en'
        # if lang not provided get the best one from the accept-language header
        else:
            lang = get_best_request_lang(request)
            if lang:
                data['lang'] = lang
            else:
                del data['lang']

        # now ensure that if we do have a lang that it's a supported one
        if 'lang' in data:
            data['lang'] = get_best_supported_lang(data['lang'])

        # if source_url not provided we should store the referrer header
        # NOTE this is not a typo; Referrer is misspelled in the HTTP spec
        # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.36
        if not data['source_url'] and request.META.get('HTTP_REFERER'):
            referrer = request.META['HTTP_REFERER']
            if SOURCE_URL_RE.match(referrer):
                statsd.incr('news.views.subscribe_main.use_referrer')
                data['source_url'] = referrer

        if is_ratelimited(request, group='basket.news.views.subscribe_main',
                          key=lambda x, y: '%s-%s' % (':'.join(data['newsletters']), data['email']),
                          rate=EMAIL_SUBSCRIBE_RATE_LIMIT, increment=True):
            statsd.incr('subscribe.ratelimited')
            return respond_error(request, form, 'Rate limit reached', 429)

        try:
            upsert_user.delay(SUBSCRIBE, data, start_time=time())
        except Exception:
            return respond_error(request, form, 'Unknown error', 500)

        return respond_ok(request, data)

    else:
        # form is invalid
        if request.is_ajax():
            return HttpResponseJSON({
                'status': 'error',
                'errors': format_form_errors(form.errors),
                'errors_by_field': form.errors,
            }, 400)
        else:
            return render(request, 'news/formerror.html', {'form': form}, status=400)
Exemple #2
0
def subscribe_main(request):
    """Subscription view for use with client side JS"""
    form = SubscribeForm(request.POST)
    if form.is_valid():
        data = form.cleaned_data

        if email_is_blocked(data['email']):
            statsd.incr('news.views.subscribe_main.email_blocked')
            # don't let on there's a problem
            return respond_ok(request, data)

        data['format'] = data.pop('fmt') or 'H'

        if data['lang']:
            if not language_code_is_valid(data['lang']):
                data['lang'] = 'en'
        # if lang not provided get the best one from the accept-language header
        else:
            lang = get_best_request_lang(request)
            if lang:
                data['lang'] = lang
            else:
                del data['lang']

        # if source_url not provided we should store the referrer header
        # NOTE this is not a typo; Referrer is misspelled in the HTTP spec
        # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.36
        if not data['source_url'] and request.META.get('HTTP_REFERER'):
            referrer = request.META['HTTP_REFERER']
            if SOURCE_URL_RE.match(referrer):
                statsd.incr('news.views.subscribe_main.use_referrer')
                data['source_url'] = referrer

        if is_ratelimited(request, group='basket.news.views.subscribe_main',
                          key=lambda x, y: '%s-%s' % (':'.join(data['newsletters']), data['email']),
                          rate=EMAIL_SUBSCRIBE_RATE_LIMIT, increment=True):
            statsd.incr('subscribe.ratelimited')
            return respond_error(request, form, 'Rate limit reached', 429)

        try:
            upsert_user.delay(SUBSCRIBE, data, start_time=time())
        except Exception:
            return respond_error(request, form, 'Unknown error', 500)

        return respond_ok(request, data)

    else:
        # form is invalid
        if request.is_ajax():
            return HttpResponseJSON({
                'status': 'error',
                'errors': format_form_errors(form.errors),
                'errors_by_field': form.errors,
            }, 400)
        else:
            return render(request, 'news/formerror.html', {'form': form}, status=400)
Exemple #3
0
    def test_exact_3_letter(self):
        """3-letter code is valid.

        There are a few of these."""
        self.assertTrue(language_code_is_valid('azq'))
Exemple #4
0
 def test_case_insensitive(self):
     """Matching is not case sensitive"""
     self.assertTrue(language_code_is_valid("az-BY"))
     self.assertTrue(language_code_is_valid("aZ"))
     self.assertTrue(language_code_is_valid("QW"))
Exemple #5
0
def get_involved(request):
    data = request.POST.dict()
    if "email" not in data:
        return HttpResponseJSON(
            {
                "status": "error",
                "desc": "email is required",
                "code": errors.BASKET_USAGE_ERROR,
            },
            401,
        )
    if email_is_blocked(data["email"]):
        # don't let on there's a problem
        return HttpResponseJSON({"status": "ok"})
    if "interest_id" not in data:
        return HttpResponseJSON(
            {
                "status": "error",
                "desc": "interest_id is required",
                "code": errors.BASKET_USAGE_ERROR,
            },
            401,
        )

    try:
        Interest.objects.get(interest_id=data["interest_id"])
    except Interest.DoesNotExist:
        return HttpResponseJSON(
            {
                "status": "error",
                "desc": "invalid interest_id",
                "code": errors.BASKET_USAGE_ERROR,
            },
            401,
        )

    if "lang" not in data:
        return HttpResponseJSON(
            {
                "status": "error",
                "desc": "lang is required",
                "code": errors.BASKET_USAGE_ERROR,
            },
            401,
        )
    if not language_code_is_valid(data["lang"]):
        return HttpResponseJSON(
            {
                "status": "error",
                "desc": "invalid language",
                "code": errors.BASKET_INVALID_LANGUAGE,
            },
            400,
        )
    if "name" not in data:
        return HttpResponseJSON(
            {
                "status": "error",
                "desc": "name is required",
                "code": errors.BASKET_USAGE_ERROR,
            },
            401,
        )
    if "country" not in data:
        return HttpResponseJSON(
            {
                "status": "error",
                "desc": "country is required",
                "code": errors.BASKET_USAGE_ERROR,
            },
            401,
        )

    email = process_email(data.get("email"))
    if not email:
        return invalid_email_response()

    update_get_involved.delay(
        data["interest_id"],
        data["lang"],
        data["name"],
        email,
        data["country"],
        data.get("format", "H"),
        data.get("subscribe", False),
        data.get("message", None),
        data.get("source_url", None),
    )
    return HttpResponseJSON({"status": "ok"})
Exemple #6
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 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'
    # if lang not provided get the best one from the accept-language header
    else:
        data['lang'] = get_best_request_lang(request) or '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='basket.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='basket.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',
        })
Exemple #7
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 is_authorized(request, data.get('email')):
                    return HttpResponseJSON({
                        'status': 'error',
                        'desc': 'private newsletter subscription requires a valid API key or OAuth',
                        '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']
    # if lang not provided get the best one from the accept-language header
    else:
        lang = get_best_request_lang(request)
        if lang:
            data['lang'] = lang

    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='basket.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='basket.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',
        })
Exemple #8
0
def get_involved(request):
    data = request.POST.dict()
    if 'email' not in data:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'email is required',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)
    if email_is_blocked(data['email']):
        # don't let on there's a problem
        return HttpResponseJSON({'status': 'ok'})
    if 'interest_id' not in data:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'interest_id is required',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)

    try:
        Interest.objects.get(interest_id=data['interest_id'])
    except Interest.DoesNotExist:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'invalid interest_id',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)

    if 'lang' not in data:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'lang is required',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)
    if not language_code_is_valid(data['lang']):
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'invalid language',
            'code': errors.BASKET_INVALID_LANGUAGE,
        }, 400)
    if 'name' not in data:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'name is required',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)
    if 'country' not in data:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'country is required',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)

    email = process_email(data.get('email'))
    if not email:
        return invalid_email_response()

    update_get_involved.delay(
        data['interest_id'],
        data['lang'],
        data['name'],
        email,
        data['country'],
        data.get('format', 'H'),
        data.get('subscribe', False),
        data.get('message', None),
        data.get('source_url', None),
    )
    return HttpResponseJSON({'status': 'ok'})
Exemple #9
0
 def test_wrong_length(self):
     """A code that's not a valid length is not valid."""
     self.assertFalse(language_code_is_valid('az-'))
     self.assertFalse(language_code_is_valid('a'))
     self.assertFalse(language_code_is_valid('azqr'))
     self.assertFalse(language_code_is_valid('az-BY2'))
Exemple #10
0
 def test_exact_5_letter(self):
     """5-letter code that's in the list is valid"""
     self.assertTrue(language_code_is_valid('az-BY'))
Exemple #11
0
    def test_exact_3_letter(self):
        """3-letter code is valid.

        There are a few of these."""
        self.assertTrue(language_code_is_valid('azq'))
Exemple #12
0
 def test_zero(self):
     """0 is a TypeError"""
     with self.assertRaises(TypeError):
         language_code_is_valid(0)
Exemple #13
0
 def test_none(self):
     """None is a TypeError"""
     with self.assertRaises(TypeError):
         language_code_is_valid(None)
Exemple #14
0
 def test_empty_string(self):
     """Empty string is accepted as a language code"""
     self.assertTrue(language_code_is_valid(''))
Exemple #15
0
 def test_exact_5_letter(self):
     """5-letter code that's in the list is valid"""
     self.assertTrue(language_code_is_valid('az-BY'))
Exemple #16
0
 def test_case_insensitive(self):
     """Matching is not case sensitive"""
     self.assertTrue(language_code_is_valid('az-BY'))
     self.assertTrue(language_code_is_valid('aZ'))
     self.assertTrue(language_code_is_valid('QW'))
Exemple #17
0
 def test_case_insensitive(self):
     """Matching is not case sensitive"""
     self.assertTrue(language_code_is_valid('az-BY'))
     self.assertTrue(language_code_is_valid('aZ'))
     self.assertTrue(language_code_is_valid('QW'))
Exemple #18
0
 def test_wrong_format(self):
     """A code that's not a valid format is not valid."""
     self.assertFalse(language_code_is_valid('a2'))
     self.assertFalse(language_code_is_valid('asdfj'))
     self.assertFalse(language_code_is_valid('az_BY'))
Exemple #19
0
 def test_wrong_length(self):
     """A code that's not a valid length is not valid."""
     self.assertFalse(language_code_is_valid('az-'))
     self.assertFalse(language_code_is_valid('a'))
     self.assertFalse(language_code_is_valid('azqr'))
     self.assertFalse(language_code_is_valid('az-BY2'))
Exemple #20
0
 def test_wrong_format(self):
     """A code that's not a valid format is not valid."""
     self.assertFalse(language_code_is_valid('a2'))
     self.assertFalse(language_code_is_valid('asdfj'))
     self.assertFalse(language_code_is_valid('az_BY'))
Exemple #21
0
 def test_empty_string(self):
     """Empty string is accepted as a language code"""
     self.assertTrue(language_code_is_valid(''))
Exemple #22
0
def get_involved(request):
    data = request.POST.dict()
    if 'email' not in data:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'email is required',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)
    if email_is_blocked(data['email']):
        # don't let on there's a problem
        return HttpResponseJSON({'status': 'ok'})
    if 'interest_id' not in data:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'interest_id is required',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)

    try:
        Interest.objects.get(interest_id=data['interest_id'])
    except Interest.DoesNotExist:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'invalid interest_id',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)

    if 'lang' not in data:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'lang is required',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)
    if not language_code_is_valid(data['lang']):
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'invalid language',
            'code': errors.BASKET_INVALID_LANGUAGE,
        }, 400)
    if 'name' not in data:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'name is required',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)
    if 'country' not in data:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'country is required',
            'code': errors.BASKET_USAGE_ERROR,
        }, 401)

    email = process_email(data.get('email'))
    if not email:
        return invalid_email_response()

    update_get_involved.delay(
        data['interest_id'],
        data['lang'],
        data['name'],
        email,
        data['country'],
        data.get('format', 'H'),
        data.get('subscribe', False),
        data.get('message', None),
        data.get('source_url', None),
    )
    return HttpResponseJSON({'status': 'ok'})
Exemple #23
0
 def test_none(self):
     """None is a TypeError"""
     with self.assertRaises(TypeError):
         language_code_is_valid(None)
Exemple #24
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 is_authorized(request, data.get("email")):
                    return HttpResponseJSON(
                        {
                            "status": "error",
                            "desc":
                            "private newsletter subscription requires a valid API key or OAuth",
                            "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"]
    # if lang not provided get the best one from the accept-language header
    else:
        lang = get_best_request_lang(request)
        if lang:
            data["lang"] = lang

    # now ensure that if we do have a lang that it's a supported one
    if "lang" in data:
        data["lang"] = get_best_supported_lang(data["lang"])

    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="basket.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="basket.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"})
Exemple #25
0
 def test_zero(self):
     """0 is a TypeError"""
     with self.assertRaises(TypeError):
         language_code_is_valid(0)
Exemple #26
0
def subscribe_main(request):
    """Subscription view for use with client side JS"""
    form = SubscribeForm(request.POST)
    if form.is_valid():
        data = form.cleaned_data

        if email_is_blocked(data["email"]):
            statsd.incr("news.views.subscribe_main.email_blocked")
            # don't let on there's a problem
            return respond_ok(request, data)

        data["format"] = data.pop("fmt") or "H"

        if data["lang"]:
            if not language_code_is_valid(data["lang"]):
                data["lang"] = "en"
        # if lang not provided get the best one from the accept-language header
        else:
            lang = get_best_request_lang(request)
            if lang:
                data["lang"] = lang
            else:
                del data["lang"]

        # now ensure that if we do have a lang that it's a supported one
        if "lang" in data:
            data["lang"] = get_best_supported_lang(data["lang"])

        # if source_url not provided we should store the referrer header
        # NOTE this is not a typo; Referrer is misspelled in the HTTP spec
        # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.36
        if not data["source_url"] and request.META.get("HTTP_REFERER"):
            referrer = request.META["HTTP_REFERER"]
            if SOURCE_URL_RE.match(referrer):
                statsd.incr("news.views.subscribe_main.use_referrer")
                data["source_url"] = referrer

        if is_ratelimited(
                request,
                group="basket.news.views.subscribe_main",
                key=lambda x, y: "%s-%s" %
            (":".join(data["newsletters"]), data["email"]),
                rate=EMAIL_SUBSCRIBE_RATE_LIMIT,
                increment=True,
        ):
            statsd.incr("subscribe.ratelimited")
            return respond_error(request, form, "Rate limit reached", 429)

        try:
            upsert_user.delay(SUBSCRIBE, data, start_time=time())
        except Exception:
            return respond_error(request, form, "Unknown error", 500)

        return respond_ok(request, data)

    else:
        # form is invalid
        if request.is_ajax():
            return HttpResponseJSON(
                {
                    "status": "error",
                    "errors": format_form_errors(form.errors),
                    "errors_by_field": form.errors,
                },
                400,
            )
        else:
            return render(request,
                          "news/formerror.html", {"form": form},
                          status=400)
Exemple #27
0
 def test_exact_2_letter(self):
     """2-letter code that's in the list is valid"""
     self.assertTrue(language_code_is_valid("az"))