From 92acf352b698bb888b6a57d5971285e510f0a649 Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Wed, 24 Mar 2021 17:30:05 +0100 Subject: [PATCH] add limiter for random alias creation --- app/dashboard/views/custom_alias.py | 2 +- app/dashboard/views/index.py | 11 +++++--- tests/dashboard/test_index.py | 39 +++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 tests/dashboard/test_index.py diff --git a/app/dashboard/views/custom_alias.py b/app/dashboard/views/custom_alias.py index 9b4ac313..7229a64b 100644 --- a/app/dashboard/views/custom_alias.py +++ b/app/dashboard/views/custom_alias.py @@ -23,7 +23,7 @@ from app.models import ( AliasMailbox, DomainDeletedAlias, ) -from app.utils import convert_to_id, random_word, word_exist +from app.utils import random_word, word_exist signer = TimestampSigner(CUSTOM_ALIAS_SECRET) diff --git a/app/dashboard/views/index.py b/app/dashboard/views/index.py index d5428ac6..bfc9f2ac 100644 --- a/app/dashboard/views/index.py +++ b/app/dashboard/views/index.py @@ -6,9 +6,9 @@ from sqlalchemy.orm import joinedload from app import alias_utils from app.api.serializer import get_alias_infos_with_pagination_v3 -from app.config import PAGE_LIMIT +from app.config import PAGE_LIMIT, ALIAS_LIMIT from app.dashboard.base import dashboard_bp -from app.extensions import db +from app.extensions import db, limiter from app.log import LOG from app.models import ( Alias, @@ -51,6 +51,11 @@ def get_stats(user: User) -> Stats: @dashboard_bp.route("/", methods=["GET", "POST"]) +@limiter.limit( + ALIAS_LIMIT, + methods=["POST"], + exempt_when=lambda: request.form.get("form-name") != "create-random-email", +) @login_required def index(): query = request.args.get("query") or "" @@ -91,7 +96,7 @@ def index(): db.session.commit() - LOG.d("generate new email %s for user %s", alias, current_user) + LOG.d("create new random alias %s for user %s", alias, current_user) flash(f"Alias {alias.email} has been created", "success") return redirect( diff --git a/tests/dashboard/test_index.py b/tests/dashboard/test_index.py new file mode 100644 index 00000000..ade7a6c4 --- /dev/null +++ b/tests/dashboard/test_index.py @@ -0,0 +1,39 @@ +from flask import url_for, g + +from app.models import ( + Alias, +) +from tests.utils import login + + +def test_create_random_alias_success(flask_client): + login(flask_client) + assert Alias.query.count() == 1 + + r = flask_client.post( + url_for("dashboard.index"), + data={"form-name": "create-random-email"}, + follow_redirects=True, + ) + assert r.status_code == 200 + assert Alias.query.count() == 2 + + +def test_too_many_requests(flask_client): + login(flask_client) + + # can't create more than 5 aliases in 1 minute + for i in range(7): + r = flask_client.post( + url_for("dashboard.index"), + data={"form-name": "create-random-email"}, + follow_redirects=True, + ) + + # to make flask-limiter work with unit test + # https://github.com/alisaifee/flask-limiter/issues/147#issuecomment-642683820 + g._rate_limiting_complete = False + else: + # last request + assert r.status_code == 429 + assert "Whoa, slow down there, pardner!" in str(r.data)