Captcha for searches

This commit is contained in:
Simon 2018-08-10 12:46:40 -04:00
parent c94cf5b313
commit c29af180c5
4 changed files with 100 additions and 66 deletions

View File

@ -14,8 +14,11 @@ Create `/config.py` and fill out the parameters. Sample config:
# Leave default values for no CAPTCHAs # Leave default values for no CAPTCHAs
CAPTCHA_LOGIN = False CAPTCHA_LOGIN = False
CAPTCHA_SUBMIT = False CAPTCHA_SUBMIT = False
CAPTCHA_SEARCH = False
CAPTCHA_SITE_KEY = "" CAPTCHA_SITE_KEY = ""
CAPTCHA_SECRET_KEY = "" CAPTCHA_SECRET_KEY = ""
CAPTCHA_S_SITE_KEY = ""
CAPTCHA_S_SECRET_KEY = ""
# Flask secret key for sessions # Flask secret key for sessions
FLASK_SECRET = "" FLASK_SECRET = ""

134
app.py
View File

@ -21,6 +21,12 @@ if config.CAPTCHA_SUBMIT or config.CAPTCHA_LOGIN:
secret_key=config.CAPTCHA_SECRET_KEY) secret_key=config.CAPTCHA_SECRET_KEY)
else: else:
recaptcha = None recaptcha = None
if config.CAPTCHA_SEARCH:
recaptcha_search = ReCaptcha(app=app,
site_key=config.CAPTCHA_S_SITE_KEY,
secret_key=config.CAPTCHA_S_SECRET_KEY)
else:
recaptcha_search = None
app.secret_key = config.FLASK_SECRET app.secret_key = config.FLASK_SECRET
db = Database("db.sqlite3") db = Database("db.sqlite3")
cache = Cache(app, config={'CACHE_TYPE': 'simple'}) cache = Cache(app, config={'CACHE_TYPE': 'simple'})
@ -243,79 +249,86 @@ def admin_rescan_website(website_id):
@app.route("/search") @app.route("/search")
def search(): def search():
q = request.args.get("q") if "q" in request.args else ""
sort_order = request.args.get("sort_order") if "sort_order" in request.args else "score"
page = request.args.get("p") if "p" in request.args else "0" q = request.args.get("q") if "q" in request.args else ""
page = int(page) if page.isdigit() else 0 sort_order = request.args.get("sort_order") if "sort_order" in request.args else "score"
per_page = request.args.get("per_page") if "per_page" in request.args else "50" page = request.args.get("p") if "p" in request.args else "0"
per_page = int(per_page) if per_page.isdigit() else "50" page = int(page) if page.isdigit() else 0
per_page = per_page if per_page in config.RESULTS_PER_PAGE else 50
extensions = request.args.get("ext") if "ext" in request.args else None per_page = request.args.get("per_page") if "per_page" in request.args else "50"
extensions = [ext.strip().strip(".").lower() for ext in extensions.split(",")] if extensions else [] per_page = int(per_page) if per_page.isdigit() else "50"
per_page = per_page if per_page in config.RESULTS_PER_PAGE else 50
size_min = request.args.get("size_min") if "size_min" in request.args else "size_min" extensions = request.args.get("ext") if "ext" in request.args else None
size_min = int(size_min) if size_min.isdigit() else 0 extensions = [ext.strip().strip(".").lower() for ext in extensions.split(",")] if extensions else []
size_max = request.args.get("size_max") if "size_max" in request.args else "size_max"
size_max = int(size_max) if size_max.isdigit() else 0
date_min = request.args.get("date_min") if "date_min" in request.args else "date_min" size_min = request.args.get("size_min") if "size_min" in request.args else "size_min"
date_min = int(date_min) if date_min.isdigit() else 0 size_min = int(size_min) if size_min.isdigit() else 0
date_max = request.args.get("date_max") if "date_max" in request.args else "date_max" size_max = request.args.get("size_max") if "size_max" in request.args else "size_max"
date_max = int(date_max) if date_max.isdigit() else 0 size_max = int(size_max) if size_max.isdigit() else 0
match_all = "all" in request.args date_min = request.args.get("date_min") if "date_min" in request.args else "date_min"
date_min = int(date_min) if date_min.isdigit() else 0
date_max = request.args.get("date_max") if "date_max" in request.args else "date_max"
date_max = int(date_max) if date_max.isdigit() else 0
field_name = "field_name" in request.args match_all = "all" in request.args
field_trigram = "field_trigram" in request.args
field_path = "field_path" in request.args
if not field_name and not field_trigram and not field_path: field_name = "field_name" in request.args
# If no fields are selected, search in all field_trigram = "field_trigram" in request.args
field_name = field_path = field_trigram = True field_path = "field_path" in request.args
fields = [] if not field_name and not field_trigram and not field_path:
if field_path: # If no fields are selected, search in all
fields.append("path") field_name = field_path = field_trigram = True
if field_name:
fields.append("name^5")
if field_trigram:
fields.append("name.nGram^2")
if len(q) >= 3: fields = []
if field_path:
fields.append("path")
if field_name:
fields.append("name^5")
if field_trigram:
fields.append("name.nGram^2")
db.log_search(request.remote_addr, if len(q) >= 3:
request.headers["X-Forwarded-For"] if "X-Forwarded-For" in request.headers else None,
q, extensions, page)
try: response = request.args.get("g-recaptcha-response", "")
hits = searchEngine.search(q, page, per_page, sort_order, if not config.CAPTCHA_SEARCH or recaptcha_search.verify(response):
extensions, size_min, size_max, match_all, fields, date_min, date_max) db.log_search(request.remote_addr,
hits = db.join_website_on_search_result(hits) request.headers["X-Forwarded-For"] if "X-Forwarded-For" in request.headers else None,
except InvalidQueryException as e: q, extensions, page)
flash("<strong>Invalid query:</strong> " + str(e), "warning")
return redirect("/search") try:
except Exception: hits = searchEngine.search(q, page, per_page, sort_order,
flash("Query failed, this could mean that the search server is overloaded or is not reachable. " extensions, size_min, size_max, match_all, fields, date_min, date_max)
"Please try again later", "danger") hits = db.join_website_on_search_result(hits)
except InvalidQueryException as e:
flash("<strong>Invalid query:</strong> " + str(e), "warning")
return redirect("/search")
except Exception:
flash("Query failed, this could mean that the search server is overloaded or is not reachable. "
"Please try again later", "danger")
hits = None
else:
flash("<strong>Error:</strong> Invalid captcha please try again", "danger")
hits = None
else:
hits = None hits = None
else: return render_template("search.html",
hits = None results=hits,
q=q,
return render_template("search.html", p=page, per_page=per_page,
results=hits, sort_order=sort_order,
q=q, results_set=config.RESULTS_PER_PAGE,
p=page, per_page=per_page, extensions=",".join(extensions),
sort_order=sort_order, size_min=size_min, size_max=size_max,
results_set=config.RESULTS_PER_PAGE, match_all=match_all,
extensions=",".join(extensions), field_trigram=field_trigram, field_path=field_path, field_name=field_name,
size_min=size_min, size_max=size_max, date_min=date_min, date_max=date_max,
match_all=match_all, show_captcha=config.CAPTCHA_SEARCH, recaptcha=recaptcha_search)
field_trigram=field_trigram, field_path=field_path, field_name=field_name,
date_min=date_min, date_max=date_max)
@app.route("/contribute") @app.route("/contribute")
@ -331,7 +344,8 @@ def home():
stats["website_count"] = len(db.get_all_websites()) stats["website_count"] = len(db.get_all_websites())
except: except:
stats = {} stats = {}
return render_template("home.html", stats=stats) return render_template("home.html", stats=stats,
show_captcha=config.CAPTCHA_SEARCH, recaptcha=recaptcha_search)
@app.route("/submit") @app.route("/submit")

View File

@ -23,13 +23,23 @@
<div class="card"> <div class="card">
<div class="card-header">Search</div> <div class="card-header">Search</div>
<div class="card-body"> <div class="card-body">
<form action="/search"> <form action="/search" id="sfrm">
<div class="form-group"> <div class="form-row">
<input class="form-control" name="q" id="q" placeholder="Query"> <div class="col-md-11">
<input class="form-control" name="q" id="q" placeholder="Query">
</div>
<div class="col-md-1">
{% if show_captcha %}
<script>function f(token) {document.getElementById("sfrm").submit();}</script>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<button class="g-recaptcha btn btn-primary btn-shadow" data-sitekey="6LcCXWkUAAAAAJo2NR9_m09Obn5YmDrI97sGrr2f" data-callback="f">Search</button>
{% else %}
<input class="btn btn-primary btn-shadow" type="submit" value="Search nocap">
{% endif %}
</div>
</div> </div>
<input class="btn btn-primary btn-shadow" type="submit" value="Search">
</form> </form>
</div> </div>
</div> </div>

View File

@ -9,7 +9,7 @@
<div class="card"> <div class="card">
<div class="card-header">Search</div> <div class="card-header">Search</div>
<div class="card-body"> <div class="card-body">
<form action="/search"> <form action="/search" id="sfrm">
<div class="form-row"> <div class="form-row">
@ -92,7 +92,14 @@
{# Search button #} {# Search button #}
<div class="form-group col-md-7"> <div class="form-group col-md-7">
<input class="btn btn-primary btn-shadow" type="submit" value="Search" style="float: right">
{% if show_captcha %}
<script>function f(token) {document.getElementById("sfrm").submit();}</script>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<button class="g-recaptcha btn btn-primary btn-shadow" data-sitekey="6LcCXWkUAAAAAJo2NR9_m09Obn5YmDrI97sGrr2f" data-callback="f" style="float: right">Search</button>
{% else %}
<input class="btn btn-primary btn-shadow" type="submit" value="Search" style="float: right">
{% endif %}
</div> </div>
</div> </div>