Exemple #1
0
 def form_valid(self, form):
     user = form.save()
     messages.success(self.request,
                      mark_safe(
                          "Successfully registered, you are now logged in! <a href='%s'>View your profile</a>" %
                          reverse('user-detail', kwargs={'pk': user.id})))
     user = authenticate(username=form.cleaned_data['username'],
                         password=form.cleaned_data['password1'])
     login(self.request, user)
     is_ratelimited(request=self.request, group=self.ratelimit_group, key=self.ratelimit_key,
                    rate=self.ratelimit_rate, increment=True)
     return super(RegistrationView, self).form_valid(form)
    def process_request(self, request):
        encoding = request.META.get('HTTP_CONTENT_ENCODING', None)

        if encoding == 'gzip':
            if is_ratelimited(request,
                              group='gunzip_request_middleware',
                              key='ip',
                              rate='300/1m',
                              increment=True):
                return http.HttpResponse(
                    'Rate limit exceeded: too many gzipped request bodies',
                    status=429)

            data = request._stream.read()
            if len(data) > settings.GUNZIP_MAX_COMPRESSED_SIZE:
                logger.warning('Compressed request body is too large: %s',
                               request.path,
                               extra={
                                   'status_code': 400,
                                   'request': request,
                               })
                return http.HttpResponseBadRequest(
                    'Compressed request body is too large')

            try:
                zfile = GzipFile(mode='rb', fileobj=StringIO(data))
                uncompressed = zfile.read()
                request._stream = LimitedStream(StringIO(uncompressed),
                                                len(uncompressed))
                del request.META['HTTP_CONTENT_ENCODING']
            except IOError:
                return http.HttpResponseBadRequest(
                    'Invalid content-encoding, could not gunzip')

        return None
Exemple #3
0
 def form_valid(self, form):
     user = form.save()
     messages.success(
         self.request,
         mark_safe(
             "Successfully registered, you are now logged in! <a href='%s'>View your profile</a>"
             % reverse('user-detail', kwargs={'pk': user.id})))
     user = authenticate(username=form.cleaned_data['username'],
                         password=form.cleaned_data['password1'])
     login(self.request, user)
     is_ratelimited(request=self.request,
                    group=self.ratelimit_group,
                    key=self.ratelimit_key,
                    rate=self.ratelimit_rate,
                    increment=True)
     return super(RegistrationView, self).form_valid(form)
Exemple #4
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 #5
0
 def do_increment(request):
     return is_ratelimited(request,
                           increment=True,
                           method=is_ratelimited.ALL,
                           key=get_key,
                           rate='1/m',
                           group='a')
Exemple #6
0
    def dispatch(self, request, *args, **kwargs):
        operation_name, is_mutation = get_gql_operation(request)

        if is_mutation:
            rate = MUTATION_RATELIMITS.get(
                operation_name,
                DEFAULT_MUTATION_RATE,
            )
        else:
            rate = QUERY_RATELIMITS.get(
                operation_name,
                DEFAULT_QUERY_RATE,
            )

        client_ip = get_client_ip(request)

        if is_ratelimited(
                request,
                group='',
                key=lambda group, request, client_ip=client_ip: client_ip,
                rate=rate,
                increment=True,
        ):
            logger.error(
                f'{get_client_ip(request)} exceeded rate limit threshold', )
            return HttpResponseTooManyRequests()

        return super().dispatch(request, *args, **kwargs)
Exemple #7
0
def confirm(request, token):
    if is_ratelimited(request, group='basket.news.views.confirm',
                      key=lambda x, y: token,
                      rate=EMAIL_SUBSCRIBE_RATE_LIMIT, increment=True):
        raise Ratelimited()
    confirm_user.delay(token, start_time=time())
    return HttpResponseJSON({'status': 'ok'})
    def dispatch(self, *args, **kwargs):
        self.setup_edx_ratelimit_config()
        request = args[0]
        request.limited = getattr(request, 'limited', False)
        rate = self.get_ratelimit_rate(request)

        ratelimited = is_ratelimited(request=request,
                                     group=self.ratelimit_group,
                                     fn=super(EdxRateLimitMixin,
                                              self).dispatch,
                                     key=self.ratelimit_key,
                                     rate=rate,
                                     method=self.ratelimit_methods,
                                     increment=True)
        if ratelimited and self.ratelimit_block:
            # add log to splunk
            logging.exception(
                'Too many request: Rate limit of {} exceeded'.format(
                    self.ratelimit_rate))

            # add log to NR
            return JsonResponse(data={
                'message':
                'Too many request: Rate limit of {} exceeded'.format(
                    self.ratelimit_rate),
                'status':
                False
            },
                                status=429)
        return super(EdxRateLimitMixin, self).dispatch(*args, **kwargs)
    def process_request(self, request):
        encoding = request.META.get('HTTP_CONTENT_ENCODING', None)

        if encoding == 'gzip':
            if is_ratelimited(request, group='gunzip_request_middleware', key='ip', rate='300/1m', increment=True):
                return http.HttpResponse('Rate limit exceeded: too many gzipped request bodies', status=429)

            data = request._stream.read()
            if len(data) > settings.GUNZIP_MAX_COMPRESSED_SIZE:
                logger.warning('Compressed request body is too large: %s', request.path,
                    extra = {
                        'status_code': 400,
                        'request': request,
                    }
                )
                return http.HttpResponseBadRequest('Compressed request body is too large')

            try:
                zfile = GzipFile(mode='rb', fileobj=StringIO(data))
                uncompressed = zfile.read()
                request._stream = LimitedStream(StringIO(uncompressed), len(uncompressed))
                del request.META['HTTP_CONTENT_ENCODING']
            except IOError:
                return http.HttpResponseBadRequest('Invalid content-encoding, could not gunzip')

        return None
Exemple #10
0
        def _wrapped(root, info, **kw):
            request = info.context

            old_limited = getattr(request, "limited", False)

            if key and key.startswith("gql:"):
                _key = key.split("gql:")[1]
                value = kw.get(_key, None)
                if not value:
                    raise ValueError(f"Cannot get key: {key}")
                request.gql_rl_field = value

                new_key = GQLRatelimitKey
            else:
                new_key = key

            ratelimited = is_ratelimited(
                request=request,
                group=group,
                fn=fn,
                key=new_key,
                rate=rate,
                method=method,
                increment=True,
            )

            request.limited = ratelimited or old_limited

            if ratelimited and block:
                logger.warn("url:<%s> is denied for <%s> in Ratelimit" %
                            (request.path, request.META["REMOTE_ADDR"]))
                raise Ratelimited("rate_limited")
            return fn(root, info, **kw)
Exemple #11
0
def confirm(request, token):
    if is_ratelimited(request, group='basket.news.views.confirm',
                      key=lambda x, y: token,
                      rate=EMAIL_SUBSCRIBE_RATE_LIMIT, increment=True):
        raise Ratelimited()
    confirm_user.delay(token, start_time=time())
    return HttpResponseJSON({'status': 'ok'})
Exemple #12
0
def ratelimit(request, group="", keys=[None], increment=True):
    checkcaptcha = False
    for key in keys:
        if key == "ip":
            group = group
            key = "ip"
        else:
            group = group + "-{}".format(key)
            key = settings.GETKEY
        if is_ratelimited(
                request,
                group=group,
                key=key,
                rate=settings.DJANGO_RATE_LIMIT,
                increment=True,
        ):
            checkcaptcha = True

    if checkcaptcha:
        if not validatecaptcha(request):
            return True
        else:
            return False

    return False
Exemple #13
0
def api_clusters(request):

    if is_ratelimited(request,
                      key="ip",
                      rate=API_REQUEST_LIMIT,
                      group="api",
                      increment=True):
        return HttpResponse(status=429)

    clusters = models.ClusterModel.objects.all()

    data = {}
    data["type"] = "FeatureCollection"
    data["features"] = []

    for cluster in clusters:

        tmp = {}
        tmp["type"] = "Feature"
        tmp["geometry"] = {}
        tmp["geometry"]["type"] = "Point"
        tmp["geometry"]["coordinates"] = [cluster.geo_long, cluster.geo_lat]
        tmp["properties"] = {}
        data["features"].append(tmp)

    return HttpResponse(status=200,
                        content_type="application/json",
                        content=JSONRenderer().render(data))
Exemple #14
0
 def not_increment(request, delta):
     return is_ratelimited(request,
                           method=is_ratelimited.ALL,
                           group='a',
                           key="ip",
                           rate='10/m',
                           increment=False,
                           delta=delta)
Exemple #15
0
    def dispatch(self, request, *args, **kwargs):
        try:
            auth = request.META['HTTP_AUTHORIZATION'].split()
        except KeyError:
            logger.info('Missing auth header')
            return HttpResponseBadRequest()

        if len(auth) != 2:
            logger.info('Bad auth format')
            return HttpResponseBadRequest()

        if auth[0] != 'Bearer':
            logger.info('Wrong auth type')
            return HttpResponseBadRequest()

        try:
            unverified_payload = jwt.decode(auth[1], verify=False)
        except Exception as e:
            logger.info(f'{type(e)}: {str(e)}')
            return HttpResponseBadRequest()

        try:
            unverified_uid = str(unverified_payload['user'])
        except KeyError:
            logger.info('Missing user id from payload')
            return HttpResponseBadRequest()

        if is_ratelimited(
            request,
            group='',
            key=lambda group, request, uid=unverified_uid: uid,
            rate='88/m',
            increment=True,
        ):
            logger.error(
                f'{get_client_ip(request)} exceeded rate limit threshold for '
                f'user {unverified_uid}',
            )
            return HttpResponseTooManyRequests()

        try:
            payload = jwt.decode(auth[1])
        except Exception as e:
            logger.info(f'{type(e)}: {str(e)}')
            return HttpResponseUnauthorized()

        try:
            user = User.objects.get(id=payload['user'])
        except User.DoesNotExist:
            logger.info('User does not exist; probably deleted account')
            return HttpResponseForbidden()
        except ValidationError as e:
            logger.info(f'{type(e)}: {str(e)}')
            return HttpResponseForbidden()

        request.user = user

        return super().dispatch(request, *args, **kwargs)
Exemple #16
0
 def dispatch(self, *args, **kwargs):
     ratelimited = is_ratelimited(request=self.request,
                                  group=self.ratelimit_group,
                                  key=self.ratelimit_key,
                                  rate=self.ratelimit_rate,
                                  increment=False)
     if ratelimited and self.ratelimit_block:
         raise Ratelimited()
     return super(RateLimitedFormView, self).dispatch(*args, **kwargs)
Exemple #17
0
def subscribe_sms(request):
    mobile = request.POST.get("mobile_number")
    if not mobile:
        return HttpResponseJSON(
            {
                "status": "error",
                "desc": "mobile_number is missing",
                "code": errors.BASKET_USAGE_ERROR,
            },
            400,
        )

    country = request.POST.get("country", "us")
    language = request.POST.get("lang", "en-US")
    msg_name = request.POST.get("msg_name", "SMS_Android")
    vendor_id = get_sms_vendor_id(msg_name, country, language)
    if not vendor_id:
        if language != "en-US":
            # if not available in the requested language, try the default
            language = "en-US"
            vendor_id = get_sms_vendor_id(msg_name, country, language)

    if not vendor_id:
        return HttpResponseJSON(
            {
                "status": "error",
                "desc": "Invalid msg_name + country + language",
                "code": errors.BASKET_USAGE_ERROR,
            },
            400,
        )

    mobile = parse_phone_number(mobile, country)
    if not mobile:
        return HttpResponseJSON(
            {
                "status": "error",
                "desc": "mobile_number is invalid",
                "code": errors.BASKET_USAGE_ERROR,
            },
            400,
        )

    # only rate limit numbers here so we don't rate limit errors.
    if is_ratelimited(
            request,
            group="basket.news.views.subscribe_sms",
            key=lambda x, y: "%s-%s" % (msg_name, mobile),
            rate=PHONE_NUMBER_RATE_LIMIT,
            increment=True,
    ):
        raise Ratelimited()

    optin = request.POST.get("optin", "N") == "Y"

    add_sms_user.delay(msg_name, mobile, optin, vendor_id=vendor_id)
    return HttpResponseJSON({"status": "ok"})
Exemple #18
0
 def get(self, request, *args, **kwargs):
     if 'kwd' in self.request.GET and is_ratelimited(
             request,
             key='header:x-forwarded-for',
             rate='20/h',
             increment=True,
             group=__name__ + '.KeywordSearchPage'):
         raise Ratelimited
     return super().get(request, *args, **kwargs)
Exemple #19
0
 def dispatch(self, *args, **kwargs):
     ratelimited = is_ratelimited(request=self.request,
                                  group=self.ratelimit_group,
                                  key=self.ratelimit_key,
                                  rate=self.ratelimit_rate,
                                  increment=False)
     if ratelimited and self.ratelimit_block:
         raise Ratelimited()
     return super(RateLimitedFormView, self).dispatch(*args, **kwargs)
Exemple #20
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 #21
0
def api_clusters_grid(request):

    if is_ratelimited(request,
                      key="ip",
                      rate=API_REQUEST_LIMIT,
                      group="api",
                      increment=True):
        return HttpResponse(status=429)

    data = {}
    data["type"] = "FeatureCollection"
    data["features"] = []

    geo_lat = decimal.Decimal(-90)

    while True:
        tmp = {}
        tmp["type"] = "Feature"
        tmp["geometry"] = {}
        tmp["geometry"]["type"] = "LineString"
        tmp["geometry"]["coordinates"] = [[
            -180 - models.CLUSTER_WIDTH_HALF,
            geo_lat - models.CLUSTER_HEIGHT_HALF
        ],
                                          [
                                              180 - models.CLUSTER_WIDTH_HALF,
                                              geo_lat -
                                              models.CLUSTER_HEIGHT_HALF
                                          ]]
        data["features"].append(tmp)
        geo_lat += models.CLUSTER_HEIGHT
        if geo_lat > 90: break

    geo_long = decimal.Decimal(-180)

    while True:
        tmp = {}
        tmp["type"] = "Feature"
        tmp["geometry"] = {}
        tmp["geometry"]["type"] = "LineString"
        tmp["geometry"]["coordinates"] = [[
            geo_long - models.CLUSTER_WIDTH_HALF,
            -90 - models.CLUSTER_HEIGHT_HALF
        ],
                                          [
                                              geo_long -
                                              models.CLUSTER_WIDTH_HALF,
                                              90 - models.CLUSTER_HEIGHT_HALF
                                          ]]
        data["features"].append(tmp)
        geo_long += models.CLUSTER_WIDTH
        if geo_long > 180: break

    return HttpResponse(status=200,
                        content_type="application/json",
                        content=JSONRenderer().render(data))
Exemple #22
0
def _login_view(request, event):
    errors = []
    if request.method == "POST":
        key = request.POST.get("key", "")
        if len(key) == 0:
            errors.append(_("Access key must be given"))
        elif is_ratelimited(request,
                            fn=_login_view,
                            key=_ratelimit_key,
                            rate=settings.KIRPPU_MOBILE_LOGIN_RATE_LIMIT,
                            increment=True):
            errors.append(_("You are trying too much. Try again later."))
        else:
            with transaction.atomic():
                try:
                    permit = TemporaryAccessPermit.objects.get(short_code=key)
                except TemporaryAccessPermit.DoesNotExist:
                    errors.append(_("Invalid access key"))
                else:
                    can_use = permit.state == TemporaryAccessPermit.STATE_UNUSED\
                              and permit.expiration_time >= timezone.now()

                    TemporaryAccessPermitLog.objects.create(
                        permit=permit,
                        action=TemporaryAccessPermitLog.ACTION_USE
                        if can_use else TemporaryAccessPermitLog.ACTION_TRY,
                        address=shorten_text(
                            get_ip(request) + "; " +
                            request.META.get("REMOTE_HOST", ""),
                            TemporaryAccessPermitLog._meta.get_field(
                                "address").max_length, False),
                        peer=shorten_text(
                            request.META.get("HTTP_USER_AGENT", ""),
                            TemporaryAccessPermitLog._meta.get_field(
                                "peer").max_length, False))

                    if can_use:
                        permit.state = TemporaryAccessPermit.STATE_IN_USE
                        permit.save(update_fields=("state", ))
                        request.session[_PERMIT_SESSION_KEY] = permit.pk
                        return HttpResponseRedirect(
                            reverse("kirppu:mobile",
                                    kwargs={"event_slug": event.slug}))
                    else:
                        errors.append(_("Invalid access key"))

    field = TemporaryAccessPermit._meta.get_field("short_code")
    min_length = first(field.validators, lambda v: v.code == "min_length")
    return render(
        request, "kirppu/vendor_status_login.html", {
            'event': event,
            'min_length': min_length.limit_value if min_length else 0,
            'max_length': field.max_length,
            'errors': errors,
        })
Exemple #23
0
        def _wrapped(request, *args, **kwargs):
            already_limited = getattr(request, 'limited', False)
            ratelimited = is_ratelimited(
                request=request, group=rulename,
                key=keyfun, rate=rate, method=['POST'],
                increment=True)

            if not already_limited and ratelimited:
                statsd.incr('throttled.' + rulename)

            return fn(request, *args, **kwargs)
Exemple #24
0
        def _wrapped(*args, **kwargs):
            request = args[0] if isinstance(args[0], HttpRequest) else args[1]
            request.limited = getattr(request, 'limited', False)

            if not getattr(settings, 'RATELIMIT_ENABLE', True):
                request.limited = False
                return fn(*args, **kwargs)

            rate_local = self.rate
            if callable(rate_local):
                rate_local = rate_local(self.group, request)

            if rate_local is None:
                """
                This has been taken from the original ratelimit function.
                Ideally it should raise ImproperlyConfigured.
                """
                return fn(*args, **kwargs)

            ban_duration = self._extract_ban_duration(self.ban, request)
            group_local = self.get_group(fn)
            key_value = self.get_key_value(group=group_local, request=request)
            ban_cache_key = self._make_ban_cache_key(group_local, rate_local,
                                                     key_value, self.method,
                                                     ban_duration)

            banned = self.is_banned(ban_cache_key)
            if banned and self.block:
                raise Ratelimited

            # Checks if the user is ratelimited.
            ratelimited = is_ratelimited(request=request,
                                         group=self.group,
                                         fn=fn,
                                         key=self.key,
                                         rate=self.rate,
                                         method=self.method,
                                         increment=True)

            if ratelimited:
                self.cache.add(ban_cache_key, ban_duration,
                               ban_duration + self.EXPIRATION_FUDGE)
                if self.block:
                    exception = Ratelimited()
                    exception.banlimit_data = {
                        "key": self.key,
                        "key_value": key_value,
                        "ban_duration": ban_duration
                    }
                    # Raise Ratelimited exception with details about banned entity.
                    raise exception
            response = fn(*args, **kwargs)
            return response
Exemple #25
0
def confirm(request, token):
    token = str(token)
    if is_ratelimited(
            request,
            group="basket.news.views.confirm",
            key=lambda x, y: token,
            rate=EMAIL_SUBSCRIBE_RATE_LIMIT,
            increment=True,
    ):
        raise Ratelimited()
    confirm_user.delay(token, start_time=time())
    return HttpResponseJSON({"status": "ok"})
 def _wrapped(*args, **kw):
     # Work as a CBV method decorator.
     if isinstance(args[0], HttpRequest):
         request = args[0]
     else:
         request = args[1]
     request.limited = getattr(request, 'limited', False)
     ratelimited = is_ratelimited(request=request, group=group, fn=fn,
                                  key=key, rate=rate, method=method,
                                  increment=True)
     if ratelimited and block:
         raise Ratelimited()
     return fn(*args, **kw)
 def _wrapped(*args, **kw):
     # Work as a CBV method decorator.
     if isinstance(args[0], HttpRequest):
         request = args[0]
     else:
         request = args[1]
     request.limited = getattr(request, 'limited', False)
     ratelimited = is_ratelimited(request=request, group=group, fn=fn,
                                  key=key, rate=rate, method=method,
                                  increment=True, reset=reset)
     if ratelimited and block:
         raise Ratelimited()
     return fn(*args, **kw)
Exemple #28
0
        def _wrapped(request, *args, **kwargs):
            already_limited = getattr(request, 'limited', False)
            ratelimited = is_ratelimited(request=request,
                                         group=rulename,
                                         key=keyfun,
                                         rate=rate,
                                         method=['POST'],
                                         increment=True)

            if not already_limited and ratelimited:
                statsd.incr('throttled.' + rulename)

            return fn(request, *args, **kwargs)
Exemple #29
0
def submit_flag(request, *, prob_id):
    """Grade a flag submission and return a JSON response"""

    # Define constants
    STATUS_FIELD = 'status'
    MESSAGE_FIELD = 'message'
    ALREADY_SOLVED_STATUS = -1
    CORRECT_STATUS = 0
    INCORRECT_STATUS = 1
    ERROR_STATUS = 2

    # Rate-limit
    if is_ratelimited(request, fn=submit_flag,
                      key=queries.competitor_key, rate='2/s', increment=True):
        return JsonResponse({
            STATUS_FIELD: ERROR_STATUS,
            MESSAGE_FIELD: "You are submitting flags too fast. Slow down!"
        })

    # Process data from the request
    flag = request.POST.get('flag', '')
    competitor = request.user.competitor

    # Grade, catching errors
    try:
        correct, message = commands.submit_flag(
            prob_id=prob_id, competitor=competitor, flag=flag)
    except models.CtfProblem.DoesNotExist:
        raise Http404()
    except commands.ProblemAlreadySolvedException:
        status = ALREADY_SOLVED_STATUS
        message = "Your team has already solved this problem!"
    except commands.FlagAlreadyTriedException:
        status = ERROR_STATUS
        message = "Your team has already tried this flag!"
    except commands.FlagSubmissionNotAllowedException:
        status = ERROR_STATUS
        message = "Your timer must have expired; reload the page."
    except commands.EmptyFlagException:
        status = ERROR_STATUS
        message = "The flag was empty."
    except:
        status = ERROR_STATUS
        message = "Something went wrong; please report this to us if it persists."
    else:
        status = CORRECT_STATUS if correct else INCORRECT_STATUS

    return JsonResponse({
        STATUS_FIELD: status,
        MESSAGE_FIELD: message
    })
Exemple #30
0
    def allow_request(self, request, view):
        already_limited = getattr(request, 'limited', False)
        ratelimited = is_ratelimited(
            request=request, group=self.rulename,
            key=self.keyfun, rate=self.rate, method=self.methods,
            increment=True)

        if ratelimited:
            if not already_limited:
                statsd.incr('throttled.' + self.rulename)
            return self.throttle_failure()

        # Did not trigger rate-limiting, so this request is allowed.
        return self.throttle_success()
 def _wrapped(*args, **kw):
     # Work as a CBV method decorator.
     if isinstance(args[0], HttpRequest):
         request = args[0]
     else:
         request = args[1]
     request.limited = getattr(request, 'limited', False)
     ratelimited = is_ratelimited(request=request, group=group, fn=fn,
                                  key=key, rate=rate, method=method,
                                  increment=True)
     if ratelimited and block:
         print 'DEBUG - decorator'
         return HttpResponseForbidden()
     return fn(*args, **kw)
Exemple #32
0
        def _wrapped(*args, **kw):
            # Work as a CBV method decorator.
            if isinstance(args[0], HttpRequest):
                request = args[0]
            else:
                request = args[1]
            request.limited = getattr(request, 'limited', False)

            rate_limit_logging(request, *args, **kw)

            # rule-out exempt
            if check_bypassed_rules(request):
                #print("ruled-out")
                return fn(*args, **kw)

            # whitelist
            if check_bypassed_ip(request):
                #print("whitelisted")
                return fn(*args, **kw)

            if is_authenticated(request.user) is False \
                    and is_ratelimited(request=request, group=nlgroup, fn=fn,
                                       key="ip", rate=nlrate, method=method,
                                       increment=True):

                if redirecturl is None:
                    # return redirect("/accounts/login/?next="+request.path)
                    raise Ratelimited()
                else:
                    return redirect("/accounts/login/?next=" + redirecturl)
            if is_authenticated(request.user) is True \
                    and is_ratelimited(request=request, group=group, fn=fn,
                                       key="user", rate=rate, method=method,
                                       increment=True):

                raise Ratelimited()
            return fn(*args, **kw)
Exemple #33
0
def subscribe_sms(request):
    mobile = request.POST.get('mobile_number')
    if not mobile:
        return HttpResponseJSON(
            {
                'status': 'error',
                'desc': 'mobile_number is missing',
                'code': errors.BASKET_USAGE_ERROR,
            }, 400)

    country = request.POST.get('country', 'us')
    language = request.POST.get('lang', 'en-US')
    msg_name = request.POST.get('msg_name', 'SMS_Android')
    vendor_id = get_sms_vendor_id(msg_name, country, language)
    if not vendor_id:
        if language != 'en-US':
            # if not available in the requested language, try the default
            language = 'en-US'
            vendor_id = get_sms_vendor_id(msg_name, country, language)

    if not vendor_id:
        return HttpResponseJSON(
            {
                'status': 'error',
                'desc': 'Invalid msg_name + country + language',
                'code': errors.BASKET_USAGE_ERROR,
            }, 400)

    mobile = parse_phone_number(mobile, country)
    if not mobile:
        return HttpResponseJSON(
            {
                'status': 'error',
                'desc': 'mobile_number is invalid',
                'code': errors.BASKET_USAGE_ERROR,
            }, 400)

    # only rate limit numbers here so we don't rate limit errors.
    if is_ratelimited(request,
                      group='basket.news.views.subscribe_sms',
                      key=lambda x, y: '%s-%s' % (msg_name, mobile),
                      rate=PHONE_NUMBER_RATE_LIMIT,
                      increment=True):
        raise Ratelimited()

    optin = request.POST.get('optin', 'N') == 'Y'

    add_sms_user.delay(msg_name, mobile, optin, vendor_id=vendor_id)
    return HttpResponseJSON({'status': 'ok'})
Exemple #34
0
    def check_rate(self,request, puzzle_id):
        request.puzzle = get_object_or_404(Puzzle, puzzle_id__iexact=puzzle_id)
        request.hunt = request.puzzle.episode.hunt
        request.team = request.hunt.team_from_user(request.user)

        limited = False
        if(request.team is not None):
            request.ratelimit_key = request.user.username
            limited = is_ratelimited(request, fn=PuzzleView.as_view(), key='user', rate='1/7s', method='POST',
                           increment=True)
        #if (not limited and not request.hunt.is_public):
        #    limited = is_ratelimited(request, fn=PuzzleView.as_view(), key=get_ratelimit_key, rate='5/m', method='POST',
        #                   increment=True)

        return limited or getattr(request, 'limited', False)
Exemple #35
0
    def allow_request(self, request, view):
        already_limited = getattr(request, 'limited', False)
        ratelimited = is_ratelimited(request=request,
                                     group=self.rulename,
                                     key=self.keyfun,
                                     rate=self.rate,
                                     method=self.methods,
                                     increment=True)

        if ratelimited:
            if not already_limited:
                statsd.incr('throttled.' + self.rulename)
            return self.throttle_failure()

        # Did not trigger rate-limiting, so this request is allowed.
        return self.throttle_success()
def is_click_ratelimited(request, ratelimits=None):
    """Returns ``True`` if this user is rate limited from clicking ads and ``False`` otherwise."""
    if ratelimits is None:
        # Explicitly set the rate limits ONLY if the parameter is `None`
        # If it is an empty list, there's simply no rate limiting
        ratelimits = settings.ADSERVER_CLICK_RATELIMITS

    for rate in ratelimits:
        if is_ratelimited(
            request,
            group="ad.click",
            key=lambda _, req: get_client_ip(req),
            rate=rate,
            increment=True,
        ):
            return True

    return False
Exemple #37
0
def subscribe_sms(request):
    mobile = request.POST.get('mobile_number')
    if not mobile:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'mobile_number is missing',
            'code': errors.BASKET_USAGE_ERROR,
        }, 400)

    country = request.POST.get('country', 'us')
    language = request.POST.get('lang', 'en-US')
    msg_name = request.POST.get('msg_name', 'SMS_Android')
    vendor_id = get_sms_vendor_id(msg_name, country, language)
    if not vendor_id:
        if language != 'en-US':
            # if not available in the requested language, try the default
            language = 'en-US'
            vendor_id = get_sms_vendor_id(msg_name, country, language)

    if not vendor_id:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'Invalid msg_name + country + language',
            'code': errors.BASKET_USAGE_ERROR,
        }, 400)

    mobile = parse_phone_number(mobile, country)
    if not mobile:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'mobile_number is invalid',
            'code': errors.BASKET_USAGE_ERROR,
        }, 400)

    # only rate limit numbers here so we don't rate limit errors.
    if is_ratelimited(request, group='basket.news.views.subscribe_sms',
                      key=lambda x, y: '%s-%s' % (msg_name, mobile),
                      rate=PHONE_NUMBER_RATE_LIMIT, increment=True):
        raise Ratelimited()

    optin = request.POST.get('optin', 'N') == 'Y'

    add_sms_user.delay(msg_name, mobile, optin, vendor_id=vendor_id)
    return HttpResponseJSON({'status': 'ok'})
Exemple #38
0
def api_hotspot_content(request):

    if is_ratelimited(request,
                      key="ip",
                      rate=API_REQUEST_LIMIT,
                      group="api",
                      increment=True):
        return HttpResponse(status=429)

    if "uuid" in request.GET:
        uuid = request.GET["uuid"]
    else:
        return HttpResponse(status=404)

    hotspot = models.HotspotModel.objects.filter(uuid=uuid).first()
    if hotspot is None:
        return HttpResponse(status=404)

    return TemplateResponse(request, "details.html", {"hotspot": hotspot})
Exemple #39
0
    def post(self, request, *args, **kwargs):
        form = self.get_form()

        blocked = is_ratelimited(
            request,
            group=self.ratelimit_group,
            key=self.ratelimit_key,
            method=self.ratelimit_method,
            rate=self.ratelimit_rate,
        )
        recent_captcha = (time.time() - request.session.get(
            "captcha_validation_time", 0)) < 86400

        if blocked and not recent_captcha:
            form.fields["captcha"] = CaptchaField()

        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)
Exemple #40
0
def api_hotspot(request):

    if is_ratelimited(request,
                      key="ip",
                      rate=API_REQUEST_LIMIT,
                      group="api",
                      increment=True):
        return HttpResponse(status=429)

    if "uuid" in request.GET:
        uuid = request.GET["uuid"]
    else:
        return HttpResponse(status=404)

    hotspot = models.HotspotModel.objects.filter(uuid=uuid).first()
    if hotspot is None:
        return HttpResponse(status=404)

    return HttpResponse(status=200,
                        content_type="application/json",
                        content=JSONRenderer().render(
                            serializers.HotspotSerializer(hotspot).data))
Exemple #41
0
        def _wrapped(*args, **kw):
            # Work as a CBV method decorator.
            if isinstance(args[0], HttpRequest):
                request = args[0]
            else:
                request = args[1]
            request.limited = getattr(request, 'limited', False)

            conf = get_ratelimit_conf()

            if conf:
                ip_whitelist_rate = get_whitelist_rate(request, key, group,
                                                       conf['ip_whitelist'])
                rate = ip_whitelist_rate if ip_whitelist_rate else conf['rate']
            else:
                rate = '5/m'
            block = conf['block'] if conf['block'] else True
            method = conf['method'] if conf['method'] else ALL
            print rate

            ratelimited = is_ratelimited(request=request,
                                         group=group,
                                         fn=fn,
                                         key=key,
                                         rate=rate,
                                         method=method,
                                         increment=True)
            if ratelimited and block:
                logging.exception(
                    'Too many request: Rate limit of {} exceeded'.format(rate))
                # add log to NR
                return JsonResponse(data={
                    'message':
                    'Too many request: Rate limit of {} exceeded'.format(rate),
                    'status':
                    False
                },
                                    status=429)
            return fn(*args, **kw)
Exemple #42
0
def subscribe_sms(request):
    if 'mobile_number' not in request.POST:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'mobile_number is missing',
            'code': errors.BASKET_USAGE_ERROR,
        }, 400)

    messages = get_sms_messages()
    msg_name = request.POST.get('msg_name', 'SMS_Android')
    if msg_name not in messages:
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'Invalid msg_name',
            'code': errors.BASKET_USAGE_ERROR,
        }, 400)

    mobile = request.POST['mobile_number']
    mobile = re.sub(r'\D+', '', mobile)
    if len(mobile) == 10:
        mobile = '1' + mobile
    elif len(mobile) != 11 or mobile[0] != '1':
        return HttpResponseJSON({
            'status': 'error',
            'desc': 'mobile_number must be a US number',
            'code': errors.BASKET_USAGE_ERROR,
        }, 400)

    # only rate limit numbers here so we don't rate limit errors.
    if is_ratelimited(request, group='news.views.subscribe_sms',
                      key=lambda x, y: '%s-%s' % (msg_name, mobile),
                      rate=PHONE_NUMBER_RATE_LIMIT, increment=True):
        raise Ratelimited()

    optin = request.POST.get('optin', 'N') == 'Y'

    add_sms_user.delay(msg_name, mobile, optin)
    return HttpResponseJSON({'status': 'ok'})
Exemple #43
0
 def do_increment(request):
     return is_ratelimited(request, increment=True,
                           method=is_ratelimited.ALL, key=get_key,
                           rate='1/m', group='a')
Exemple #44
0
 def not_increment(request):
     return is_ratelimited(
         request, increment=False, method=is_ratelimited.ALL, key=get_key, rate="1/m", group="a"
     )
Exemple #45
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',
        })