mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-17 15:53:28 +00:00
@@ -35,6 +35,7 @@ from seahub.options.models import UserOptions
|
||||
from seahub.profile.models import Profile
|
||||
from seahub.two_factor.views.login import is_device_remembered
|
||||
from seahub.utils import render_error, get_site_name, is_valid_email
|
||||
from seahub.utils.http import rate_limit
|
||||
from seahub.utils.ip import get_remote_ip
|
||||
from seahub.utils.file_size import get_quota_from_string
|
||||
from seahub.utils.two_factor_auth import two_factor_auth_enabled, handle_two_factor_auth
|
||||
@@ -346,10 +347,14 @@ def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_N
|
||||
# prompts for a new password
|
||||
# - password_reset_complete shows a success message for the above
|
||||
|
||||
|
||||
@csrf_protect
|
||||
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
|
||||
@rate_limit()
|
||||
def password_reset(request, is_admin_site=False,
|
||||
template_name='registration/password_reset_form.html',
|
||||
email_template_name='registration/password_reset_email.html',
|
||||
password_reset_form=PasswordResetForm, token_generator=default_token_generator,
|
||||
password_reset_form=PasswordResetForm,
|
||||
token_generator=default_token_generator,
|
||||
post_reset_redirect=None):
|
||||
|
||||
has_bind_social_auth = False
|
||||
|
@@ -346,6 +346,9 @@ LOGOUT_REDIRECT_URL = None
|
||||
|
||||
ACCOUNT_ACTIVATION_DAYS = 7
|
||||
|
||||
REQUEST_RATE_LIMIT_NUMBER = 3
|
||||
REQUEST_RATE_LIMIT_PERIOD = 60 # seconds
|
||||
|
||||
# allow seafile admin view user's repo
|
||||
ENABLE_SYS_ADMIN_VIEW_REPO = False
|
||||
|
||||
|
@@ -1,10 +1,18 @@
|
||||
# Copyright (c) 2012-2016 Seafile Ltd.
|
||||
|
||||
|
||||
import time
|
||||
import json
|
||||
|
||||
from functools import wraps
|
||||
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
|
||||
from django.core.cache import cache
|
||||
from django.utils.translation import gettext as _
|
||||
from django.http import HttpResponse, HttpResponseBadRequest, \
|
||||
HttpResponseForbidden
|
||||
|
||||
from seahub.settings import REQUEST_RATE_LIMIT_NUMBER, \
|
||||
REQUEST_RATE_LIMIT_PERIOD
|
||||
|
||||
JSON_CONTENT_TYPE = 'application/json; charset=utf-8'
|
||||
|
||||
|
||||
class _HTTPException(Exception):
|
||||
def __init__(self, message=''):
|
||||
@@ -13,13 +21,15 @@ class _HTTPException(Exception):
|
||||
def __str__(self):
|
||||
return '%s: %s' % (self.__class__.__name__, self.message)
|
||||
|
||||
|
||||
class BadRequestException(_HTTPException):
|
||||
pass
|
||||
|
||||
|
||||
class RequestForbbiddenException(_HTTPException):
|
||||
pass
|
||||
|
||||
JSON_CONTENT_TYPE = 'application/json; charset=utf-8'
|
||||
|
||||
def json_response(func):
|
||||
@wraps(func)
|
||||
def wrapped(*a, **kw):
|
||||
@@ -36,6 +46,7 @@ def json_response(func):
|
||||
content_type=JSON_CONTENT_TYPE)
|
||||
return wrapped
|
||||
|
||||
|
||||
def int_param(request, key):
|
||||
v = request.GET.get(key, None)
|
||||
if not v:
|
||||
@@ -44,3 +55,37 @@ def int_param(request, key):
|
||||
return int(v)
|
||||
except ValueError:
|
||||
raise BadRequestException()
|
||||
|
||||
|
||||
def rate_limit(number=REQUEST_RATE_LIMIT_NUMBER,
|
||||
period=REQUEST_RATE_LIMIT_PERIOD):
|
||||
"""
|
||||
:param number: number of requests
|
||||
:param period: second
|
||||
"""
|
||||
def decorator(func):
|
||||
|
||||
@wraps(func)
|
||||
def wrapped(request, *args, **kwargs):
|
||||
|
||||
if REQUEST_RATE_LIMIT_NUMBER > 0 and \
|
||||
REQUEST_RATE_LIMIT_PERIOD > 0:
|
||||
|
||||
ip = request.META.get('REMOTE_ADDR')
|
||||
cache_key = f"rate_limit:{ip}"
|
||||
|
||||
current_time = time.time()
|
||||
data = cache.get(cache_key, {'count': 0, 'start_time': current_time})
|
||||
if current_time - data['start_time'] > period:
|
||||
data = {'count': 1, 'start_time': current_time}
|
||||
else:
|
||||
data['count'] += 1
|
||||
|
||||
cache.set(cache_key, data, timeout=period)
|
||||
|
||||
if data['count'] > number:
|
||||
return HttpResponse(_("Too many requests"), status=429)
|
||||
|
||||
return func(request, *args, **kwargs)
|
||||
return wrapped
|
||||
return decorator
|
||||
|
Reference in New Issue
Block a user