diff --git a/app/__init__.py b/app/__init__.py index 4958739aa4..b2920256bd 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -11,6 +11,7 @@ from flask_script import Manager from flask_login import current_user from flask_jwt import JWT +from flask_limiter import Limiter from datetime import timedelta from flask_cors import CORS from flask_rest_jsonapi.errors import jsonapi_errors @@ -50,6 +51,7 @@ static_dir = os.path.dirname(os.path.dirname(__file__)) + "/static" template_dir = os.path.dirname(__file__) + "/templates" app = Flask(__name__, static_folder=static_dir, template_folder=template_dir) +limiter = Limiter(app) env.read_envfile() diff --git a/app/api/auth.py b/app/api/auth.py index 873734e581..de2a8d15e5 100644 --- a/app/api/auth.py +++ b/app/api/auth.py @@ -8,11 +8,13 @@ from functools import wraps from flask import request, jsonify, make_response, Blueprint, send_file, url_for, redirect from flask_jwt import current_identity as current_user, jwt_required +from flask_limiter.util import get_remote_address from sqlalchemy.orm.exc import NoResultFound from app.api.helpers.order import create_pdf_tickets_for_holder from app.api.helpers.storage import generate_hash from app import get_settings +from app import limiter from app.api.helpers.db import save_to_db, get_count from app.api.helpers.errors import ForbiddenError, UnprocessableEntityError, NotFoundError, BadRequestError from app.api.helpers.files import make_frontend_url @@ -29,7 +31,6 @@ from app.models.user import User from app.api.helpers.storage import UPLOAD_PATHS - authorised_blueprint = Blueprint('authorised_blueprint', __name__, url_prefix='/') ticket_blueprint = Blueprint('ticket_blueprint', __name__, url_prefix='/v1') auth_routes = Blueprint('auth', __name__, url_prefix='/v1/auth') @@ -207,6 +208,12 @@ def resend_verification_email(): @auth_routes.route('/reset-password', methods=['POST']) +@limiter.limit( + '3/hour', key_func=lambda: request.json['data']['email'], error_message='Limit for this action exceeded' +) +@limiter.limit( + '1/minute', key_func=get_remote_address, error_message='Limit for this action exceeded' +) def reset_password_post(): try: email = request.json['data']['email'] diff --git a/requirements/common.txt b/requirements/common.txt index ab46ac114b..33f9789aed 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -1,5 +1,6 @@ pycparser==2.14 # Only 2.14 works. Flask~=1.0.3 +Flask-Limiter~=1.0.1 Flask-Script~=2.0.6 Flask-SQLAlchemy~=2.1 Flask-Migrate~=2.5