diff --git a/requirements.txt b/requirements.txt index a4770ae..9cbfe1e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ MarkupSafe bleach web-mini flask-limiter +flask-ishuman diff --git a/src/aw/__init__.py b/src/aw/__init__.py index 996270c..5b92054 100644 --- a/src/aw/__init__.py +++ b/src/aw/__init__.py @@ -53,6 +53,10 @@ def create_app(name: str) -> flask.Flask: app.config["USE_SESSION_FOR_NEXT"] = True + from .c import c + + c.init_app(app) + from .models import Counter, db with app.app_context(): diff --git a/src/aw/c.py b/src/aw/c.py new file mode 100644 index 0000000..c04d486 --- /dev/null +++ b/src/aw/c.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""captcha""" + +from flask_ishuman import IsHuman + +c: IsHuman = IsHuman() diff --git a/src/aw/views.py b/src/aw/views.py index c8e5c3f..9ffa9eb 100644 --- a/src/aw/views.py +++ b/src/aw/views.py @@ -11,6 +11,7 @@ import validators from werkzeug.wrappers import Response from . import email, models, util +from .c import c from .limiter import limiter from .routing import Bp @@ -130,10 +131,13 @@ def delete(comment_id: int, token: str): def comment(): """publish a comment""" - for field in "name", "email", "comment": + for field in "name", "email", "comment", "code": if field not in flask.request.form: flask.abort(400) + if not c.verify(flask.request.form["code"]): # type: ignore + flask.abort(403) + if not validators.email(flask.request.form["email"]): flask.abort(400) @@ -308,6 +312,12 @@ def badge_yellow() -> Response: return r +@views.get("/captcha.png") +def captcha() -> Response: + """CAPTCHA""" + return flask.Response(c.new().rawpng(), mimetype="image/png") + + @views.get("/btc") def btc() -> Response: """Bitcoin address""" diff --git a/src/static/css/index.css b/src/static/css/index.css index 093b66c..b58b557 100644 --- a/src/static/css/index.css +++ b/src/static/css/index.css @@ -108,6 +108,18 @@ form > button { width: 100%; } +.captcha { + display: -ms-grid; + display: grid; + place-items: center; + margin: 0.5em; +} + +.captcha > img { + display: block; + cursor: pointer; +} + @-webkit-keyframes grow { from { -webkit-transform: scaleY(0); diff --git a/src/templates/index.j2 b/src/templates/index.j2 index 3e24088..9f240e9 100644 --- a/src/templates/index.j2 +++ b/src/templates/index.j2 @@ -435,6 +435,16 @@ +
+ An image CAPTCHA + Click the image above to reload and get a new CAPTCHA. +
+ +
+ + +
+