예제 #1
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'))
예제 #2
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'))
예제 #3
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'))
예제 #4
0
 def test_none(self):
     """None is a TypeError"""
     with self.assertRaises(TypeError):
         language_code_is_valid(None)
예제 #5
0
 def test_zero(self):
     """0 is a TypeError"""
     with self.assertRaises(TypeError):
         language_code_is_valid(0)
예제 #6
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)

    try:
        validate_email(data.get('email'))
    except EmailValidationError as e:
        return invalid_email_response(e)

    update_get_involved.delay(
        data['interest_id'],
        data['lang'],
        data['name'],
        data['email'],
        data['country'],
        data.get('format', 'H'),
        data.get('subscribe', False),
        data.get('message', None),
        data.get('source_url', None),
    )
    return HttpResponseJSON({'status': 'ok'})
예제 #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 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',
        })
예제 #8
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'))
예제 #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'))
예제 #10
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'))
예제 #11
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'))
예제 #12
0
 def test_zero(self):
     """0 is a TypeError"""
     with self.assertRaises(TypeError):
         language_code_is_valid(0)
예제 #13
0
 def test_none(self):
     """None is a TypeError"""
     with self.assertRaises(TypeError):
         language_code_is_valid(None)
예제 #14
0
 def test_empty_string(self):
     """Empty string is accepted as a language code"""
     self.assertTrue(language_code_is_valid(''))
예제 #15
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'))
예제 #16
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'))
예제 #17
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'))
예제 #18
0
 def test_empty_string(self):
     """Empty string is accepted as a language code"""
     self.assertTrue(language_code_is_valid(''))
예제 #19
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',
        })
예제 #20
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'})