From ac43d0e3e36abad0c8629e53d67f8957b93bf8fa Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Mon, 3 Aug 2020 15:38:08 -0700 Subject: [PATCH 01/13] Move local_redirect to utils --- src/replit/maqpy/__init__.py | 16 ---------------- src/replit/maqpy/utils.py | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/replit/maqpy/__init__.py b/src/replit/maqpy/__init__.py index 67f1485..d24af6f 100644 --- a/src/replit/maqpy/__init__.py +++ b/src/replit/maqpy/__init__.py @@ -17,19 +17,3 @@ signed_in = LocalProxy(lambda: flask.request.signed_in) request = LocalProxy(lambda: flask.request) render_template = flask.render_template redirect = flask.redirect - - -def local_redirect(location: str, code: int = 302) -> flask.Response: - """Perform a redirection to a local path without downgrading to HTTP. - - Args: - location (str): The path to redirect to. - code (int): The code to use for the redirect. Defaults to 302. - - Returns: - flask.Response: The redirect response. - """ - # Use a LocalProxy so that it can be called before the request context is available - return LocalProxy( - lambda: redirect("https://" + request.headers["host"] + location, code) - ) diff --git a/src/replit/maqpy/utils.py b/src/replit/maqpy/utils.py index 38e1e1b..7c89322 100644 --- a/src/replit/maqpy/utils.py +++ b/src/replit/maqpy/utils.py @@ -3,6 +3,7 @@ from functools import wraps from typing import Any, Callable, Union import flask +from werkzeug.local import LocalProxy from .html import Page @@ -112,3 +113,21 @@ def needs_params( return handler return decorator + + +def local_redirect(location: str, code: int = 302) -> flask.Response: + """Perform a redirection to a local path without downgrading to HTTP. + + Args: + location (str): The path to redirect to. + code (int): The code to use for the redirect. Defaults to 302. + + Returns: + flask.Response: The redirect response. + """ + # Use a LocalProxy so that it can be called before the request context is available + return LocalProxy( + lambda: flask.redirect( + "https://" + flask.request.headers["host"] + location, code + ) + ) From 2c3ece9852856957862b97d5ed5dde4f7df3a2b3 Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Mon, 3 Aug 2020 17:16:52 -0700 Subject: [PATCH 02/13] Update dependencies --- poetry.lock | 84 ++------------------------------------------------ pyproject.toml | 1 - 2 files changed, 3 insertions(+), 82 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8022d7e..86d781b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -24,25 +24,6 @@ optional = false python-versions = "*" version = "0.7.12" -[[package]] -category = "main" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -name = "anyio" -optional = false -python-versions = ">=3.5.3" -version = "1.4.0" - -[package.dependencies] -async-generator = "*" -idna = ">=2.8" -sniffio = ">=1.1" - -[package.extras] -curio = ["curio (>=0.9)"] -doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] -test = ["coverage (>=4.5)", "hypothesis (>=4.0)", "pytest (>=3.7.2)", "uvloop"] -trio = ["trio (>=0.12)"] - [[package]] category = "dev" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." @@ -51,27 +32,6 @@ optional = false python-versions = "*" version = "1.4.4" -[[package]] -category = "main" -description = "asks - async http" -name = "asks" -optional = false -python-versions = "*" -version = "2.4.8" - -[package.dependencies] -anyio = "<2" -async_generator = "*" -h11 = "*" - -[[package]] -category = "main" -description = "Async generators and context managers for Python 3.5+" -name = "async-generator" -optional = false -python-versions = ">=3.5" -version = "1.10" - [[package]] category = "main" description = "Timeout context manager for asyncio programs" @@ -116,9 +76,9 @@ version = "1.6.2" [package.dependencies] GitPython = ">=1.0.1" PyYAML = ">=3.13" -colorama = ">=0.3.9" six = ">=1.10.0" stevedore = ">=1.20.0" +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} [[package]] category = "dev" @@ -167,7 +127,6 @@ version = "7.1.2" [[package]] category = "dev" description = "Cross-platform colored terminal text." -marker = "platform_system == \"Windows\" or sys_platform == \"win32\"" name = "colorama" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" @@ -273,7 +232,6 @@ version = "0.18.1" [package.dependencies] pycodestyle = "*" -setuptools = "*" [[package]] category = "dev" @@ -327,14 +285,6 @@ version = "3.1.7" [package.dependencies] gitdb = ">=4.0.1,<5" -[[package]] -category = "main" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -name = "h11" -optional = false -python-versions = "*" -version = "0.9.0" - [[package]] category = "main" description = "Internationalized Domain Names in Applications (IDNA)" @@ -526,14 +476,6 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "3.0.4" -[[package]] -category = "main" -description = "Sniff out which async library your code is running under" -name = "sniffio" -optional = false -python-versions = ">=3.5" -version = "1.1.0" - [[package]] category = "dev" description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." @@ -555,12 +497,10 @@ Jinja2 = ">=2.3" Pygments = ">=2.0" alabaster = ">=0.7,<0.8" babel = ">=1.3" -colorama = ">=0.3.5" docutils = ">=0.12" imagesize = "*" packaging = "*" requests = ">=2.5.0" -setuptools = "*" snowballstemmer = ">=1.1" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" @@ -568,6 +508,7 @@ sphinxcontrib-htmlhelp = "*" sphinxcontrib-jsmath = "*" sphinxcontrib-qthelp = "*" sphinxcontrib-serializinghtml = "*" +colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} [package.extras] docs = ["sphinxcontrib-websupport"] @@ -747,7 +688,7 @@ idna = ">=2.0" multidict = ">=4.0" [metadata] -content-hash = "e4e37adaadf6628a7aeac64abcb6c944266a6565fe108ff29eb72e816edf6f33" +content-hash = "93d94d333f6a693b503220db880ca32a9115d2d29a9c3cf8dac4b597c7152ed6" python-versions = "^3.8" [metadata.files] @@ -769,21 +710,10 @@ alabaster = [ {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, ] -anyio = [ - {file = "anyio-1.4.0-py3-none-any.whl", hash = "sha256:9ee67e8131853f42957e214d4531cee6f2b66dda164a298d9686a768b7161a4f"}, - {file = "anyio-1.4.0.tar.gz", hash = "sha256:95f60964fc4583f3f226f8dc275dfb02aefe7b39b85a999c6d14f4ec5323c1d8"}, -] appdirs = [ {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] -asks = [ - {file = "asks-2.4.8.tar.gz", hash = "sha256:dcf3b0e80b185430cac1e563a97b2630062893adbb73655d5e8600c83ab63342"}, -] -async-generator = [ - {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"}, - {file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"}, -] async-timeout = [ {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, @@ -870,10 +800,6 @@ gitpython = [ {file = "GitPython-3.1.7-py3-none-any.whl", hash = "sha256:fa3b92da728a457dd75d62bb5f3eb2816d99a7fe6c67398e260637a40e3fafb5"}, {file = "GitPython-3.1.7.tar.gz", hash = "sha256:2db287d71a284e22e5c2846042d0602465c7434d910406990d5b74df4afb0858"}, ] -h11 = [ - {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, - {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, -] idna = [ {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, @@ -1032,10 +958,6 @@ smmap = [ {file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"}, {file = "smmap-3.0.4.tar.gz", hash = "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"}, ] -sniffio = [ - {file = "sniffio-1.1.0-py3-none-any.whl", hash = "sha256:20ed6d5b46f8ae136d00b9dcb807615d83ed82ceea6b2058cecb696765246da5"}, - {file = "sniffio-1.1.0.tar.gz", hash = "sha256:8e3810100f69fe0edd463d02ad407112542a11ffdc29f67db2bf3771afb87a21"}, -] snowballstemmer = [ {file = "snowballstemmer-2.0.0-py2.py3-none-any.whl", hash = "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0"}, {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"}, diff --git a/pyproject.toml b/pyproject.toml index 6aeb8da..3289504 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,6 @@ requests = "^2.24.0" typing_extensions = "^3.7.4" flask = "^1.1.2" werkzeug = "^1.0.1" -asks = "^2.4.8" aiohttp = "^3.6.2" [tool.poetry.dev-dependencies] From 0a33fd77f746006c7d5b13a29082d04324077202 Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Mon, 3 Aug 2020 17:33:38 -0700 Subject: [PATCH 03/13] Rename signin to sign_in --- src/replit/maqpy/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/replit/maqpy/utils.py b/src/replit/maqpy/utils.py index 7c89322..3537cb8 100644 --- a/src/replit/maqpy/utils.py +++ b/src/replit/maqpy/utils.py @@ -14,7 +14,7 @@ sign_in_snippet = ( ) -def signin(title: str = "Please Sign In") -> Page: +def sign_in(title: str = "Please Sign In") -> Page: """Return a sign-in page. Args: From 6f590fdf1262027ed887e3f26818f8205ec87c81 Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Mon, 3 Aug 2020 17:35:43 -0700 Subject: [PATCH 04/13] Bugfix: Use signin() for needs_sign_in default Without this, sign in button was created in page head making it invisible --- src/replit/maqpy/utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/replit/maqpy/utils.py b/src/replit/maqpy/utils.py index 3537cb8..1c37566 100644 --- a/src/replit/maqpy/utils.py +++ b/src/replit/maqpy/utils.py @@ -26,7 +26,10 @@ def sign_in(title: str = "Please Sign In") -> Page: return Page(title=title, body=sign_in_snippet) -def needs_signin(func: Callable = None, login_html: str = sign_in_snippet) -> Callable: +sign_in_page = sign_in() + + +def needs_sign_in(func: Callable = None, login_res: str = sign_in_page) -> Callable: """A decorator that enforces that the user is signed in before accessing the page. Args: From 7854e5e2c12d64ad01d304809e3b2127c336dd23 Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Mon, 3 Aug 2020 18:01:41 -0700 Subject: [PATCH 05/13] Add authed ratelimit --- src/replit/maqpy/utils.py | 66 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/replit/maqpy/utils.py b/src/replit/maqpy/utils.py index 1c37566..2b52cd3 100644 --- a/src/replit/maqpy/utils.py +++ b/src/replit/maqpy/utils.py @@ -1,5 +1,6 @@ """Utitilities to make development easier.""" from functools import wraps +import time from typing import Any, Callable, Union import flask @@ -35,7 +36,7 @@ def needs_sign_in(func: Callable = None, login_res: str = sign_in_page) -> Calla Args: func (Callable): The function passed in if used as a decorator. Defaults to None. - login_html (str): The HTML to show when the user needs to sign in. Defaults to + login_res (str): The HTML to show when the user needs to sign in. Defaults to sign_in_snippet. Returns: @@ -48,7 +49,7 @@ def needs_sign_in(func: Callable = None, login_res: str = sign_in_page) -> Calla if flask.request.signed_in: return func(*args, **kwargs) else: - return login_html + return login_res return handler @@ -134,3 +135,64 @@ def local_redirect(location: str, code: int = 302) -> flask.Response: "https://" + flask.request.headers["host"] + location, code ) ) + + +def authed_ratelimit( + max_requests: int, + period: float, + login_res: str = sign_in_page, + get_ratelimited_res: Callable[[float], str] = ( + lambda left: f"Too many requests, wait {left} sec" + ), +) -> Callable[[Callable], flask.Response]: + """Require sign in and limit the amount of requests each signed in user can perform. + + This decorator also calls needs_signin for you and passes the login_res kwarg + directly to it. + + Args: + max_requests (int): The maximum amount of requests allowed in the period. + period (float): The length of the period. + login_res (str): The response to be shown if the user is not signed in, passed + to needs_sign_in. + get_ratelimited_res (Callable[[float], str]): A callable which is passed the + amount of time remaining before the user can request again and returns the + response that should be sent to the user. + + Returns: + Callable[[Callable], flask.Response]: A function which decorates the handler. + """ + + def decorator(func: Callable) -> flask.Response: + last_reset = time.time() + num_requests = {} + + # Checks for signin first, before checking ratelimit + @needs_sign_in(login_res=login_res) + @wraps(func) + def handler(*args: Any, **kwargs: Any) -> flask.Response: + nonlocal last_reset + nonlocal num_requests + + name = flask.request.auth.name + now = time.time() + + if now - last_reset >= period: + last_reset = now + num_requests = {} + + times_requested = num_requests.get(name, 0) + if times_requested >= max_requests: + res = get_ratelimited_res(period - (now - last_reset)) + # Make a reponse object so that status can be set + if not isinstance(res, flask.Response): + res = flask.make_response(res) + res.status = "429" + return res + + num_requests[name] = times_requested + 1 + return func(*args, **kwargs) + + return handler + + return decorator From b3d8963da3b06bb4b50f79fc07cb83f744bca38e Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Mon, 3 Aug 2020 18:07:44 -0700 Subject: [PATCH 06/13] Use new name of needs_sign_in in example --- examples/maqpy/{needs_signin.py => needs_sign_in.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename examples/maqpy/{needs_signin.py => needs_sign_in.py} (74%) diff --git a/examples/maqpy/needs_signin.py b/examples/maqpy/needs_sign_in.py similarity index 74% rename from examples/maqpy/needs_signin.py rename to examples/maqpy/needs_sign_in.py index c8c4b6f..dd65c5d 100644 --- a/examples/maqpy/needs_signin.py +++ b/examples/maqpy/needs_sign_in.py @@ -4,14 +4,14 @@ app = maqpy.App(__name__) @app.route("/") -@maqpy.needs_signin(login_html=f"Hello! {maqpy.sign_in_snippet}") +@maqpy.needs_sign_in(login_html=f"Hello! {maqpy.sign_in_snippet}") def index(): return "Index function" # needs_signin can also be called with no args @app.route("/test") -@maqpy.needs_signin +@maqpy.needs_sign_in def test(): return "Test function" From da943e92cac56719f30cc2e23ebed51263fd160f Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Mon, 3 Aug 2020 18:08:18 -0700 Subject: [PATCH 07/13] Use new login_res kwarg name for needs_sign_in --- examples/maqpy/needs_sign_in.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/maqpy/needs_sign_in.py b/examples/maqpy/needs_sign_in.py index dd65c5d..fb23a87 100644 --- a/examples/maqpy/needs_sign_in.py +++ b/examples/maqpy/needs_sign_in.py @@ -4,7 +4,7 @@ app = maqpy.App(__name__) @app.route("/") -@maqpy.needs_sign_in(login_html=f"Hello! {maqpy.sign_in_snippet}") +@maqpy.needs_sign_in(login_res=f"Hello! {maqpy.sign_in_snippet}") def index(): return "Index function" From b055deb4132b7894340e5818719f4cbd546e1247 Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Mon, 3 Aug 2020 18:13:00 -0700 Subject: [PATCH 08/13] Add authed_ratelimit example --- examples/maqpy/authed_ratelimit.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 examples/maqpy/authed_ratelimit.py diff --git a/examples/maqpy/authed_ratelimit.py b/examples/maqpy/authed_ratelimit.py new file mode 100644 index 0000000..9a9a0e6 --- /dev/null +++ b/examples/maqpy/authed_ratelimit.py @@ -0,0 +1,18 @@ +from replit import maqpy + +app = maqpy.App(__name__) + + +@app.route("/") +@maqpy.authed_ratelimited( + limit=1, # Number of requests allowed + period=1, # Amount of time before counter resets + login_res=maqpy.Page(body=f"Sign in\n{maqpy.sign_in_snippet}"), + get_ratelimited_res=(lambda left: f"Too many requests, try again after {left} sec"), +) +def index(): + return "You can request this page once per second" + + +if __name__ == "__main__": + app.run() From 8ce9d9903e74ac70a0e93c82a5181556eed43e22 Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Tue, 4 Aug 2020 12:36:23 -0700 Subject: [PATCH 09/13] Import new utils functions in maqpy init --- src/replit/maqpy/__init__.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/replit/maqpy/__init__.py b/src/replit/maqpy/__init__.py index d24af6f..f9e3767 100644 --- a/src/replit/maqpy/__init__.py +++ b/src/replit/maqpy/__init__.py @@ -9,7 +9,15 @@ from . import html from .app import App from .files import File from .html import HTMLElement, Link, Page, Paragraph -from .utils import needs_params, needs_signin, sign_in_snippet, signin +from .utils import ( + needs_params, + needs_sign_in, + sign_in_snippet, + sign_in_page, + sign_in, + local_redirect, + authed_ratelimit, +) from ..database import db auth = LocalProxy(lambda: flask.request.auth) From 7674192f1f2e9e8452345410dd41ffb663a70aca Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Tue, 4 Aug 2020 12:39:29 -0700 Subject: [PATCH 10/13] Put imports in correct order --- src/replit/maqpy/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/replit/maqpy/__init__.py b/src/replit/maqpy/__init__.py index f9e3767..804a26a 100644 --- a/src/replit/maqpy/__init__.py +++ b/src/replit/maqpy/__init__.py @@ -10,13 +10,13 @@ from .app import App from .files import File from .html import HTMLElement, Link, Page, Paragraph from .utils import ( + authed_ratelimit, + local_redirect, needs_params, needs_sign_in, - sign_in_snippet, - sign_in_page, sign_in, - local_redirect, - authed_ratelimit, + sign_in_page, + sign_in_snippet, ) from ..database import db From 47ccdb8f7719a0c38c4ebc37baae3ed6e5756080 Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Tue, 4 Aug 2020 12:39:58 -0700 Subject: [PATCH 11/13] Use new sign_in over old signin util --- src/replit/maqpy/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/replit/maqpy/app.py b/src/replit/maqpy/app.py index c033ccd..a72de74 100644 --- a/src/replit/maqpy/app.py +++ b/src/replit/maqpy/app.py @@ -5,7 +5,7 @@ from typing import Any, Callable, Set import flask -from .utils import signin +from .utils import sign_in @dataclass @@ -84,7 +84,7 @@ class App(flask.Flask): not provided, defaults to maqpy.signin() """ self._lw_exclude = set(exclude) or set() - self._lw_handler = handler or (lambda: signin()) + self._lw_handler = handler or (lambda: sign_in()) def _request_handler(self, rule: str, view_func: Callable) -> Callable: """Return a handler for a given request. From dcbbaebcf72d999875a3c17934d48b33c49ebf15 Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Tue, 4 Aug 2020 12:45:39 -0700 Subject: [PATCH 12/13] Fix typo in ratelimit example --- examples/maqpy/authed_ratelimit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/maqpy/authed_ratelimit.py b/examples/maqpy/authed_ratelimit.py index 9a9a0e6..e807702 100644 --- a/examples/maqpy/authed_ratelimit.py +++ b/examples/maqpy/authed_ratelimit.py @@ -4,7 +4,7 @@ app = maqpy.App(__name__) @app.route("/") -@maqpy.authed_ratelimited( +@maqpy.authed_ratelimit( limit=1, # Number of requests allowed period=1, # Amount of time before counter resets login_res=maqpy.Page(body=f"Sign in\n{maqpy.sign_in_snippet}"), From b10b0212abd69367bb48968eb3ce46e909bff7e1 Mon Sep 17 00:00:00 2001 From: Scoder12 <34356756+Scoder12@users.noreply.github.com> Date: Tue, 4 Aug 2020 12:46:23 -0700 Subject: [PATCH 13/13] Use correct kwarg name in ratelimit example --- examples/maqpy/authed_ratelimit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/maqpy/authed_ratelimit.py b/examples/maqpy/authed_ratelimit.py index e807702..6b5337e 100644 --- a/examples/maqpy/authed_ratelimit.py +++ b/examples/maqpy/authed_ratelimit.py @@ -5,7 +5,7 @@ app = maqpy.App(__name__) @app.route("/") @maqpy.authed_ratelimit( - limit=1, # Number of requests allowed + max_requests=1, # Number of requests allowed period=1, # Amount of time before counter resets login_res=maqpy.Page(body=f"Sign in\n{maqpy.sign_in_snippet}"), get_ratelimited_res=(lambda left: f"Too many requests, try again after {left} sec"),