fix bug + add captcha
This commit is contained in:
parent
979d0079d7
commit
c96c84b836
@ -46,4 +46,7 @@ max_accounts = 50
|
||||
mandatory_email = yes
|
||||
# whether or not the user must give an password to subscribe
|
||||
# at least one of email and password is mandatory
|
||||
mandatory_password = yes
|
||||
mandatory_password = yes
|
||||
# path to db managing the captcha
|
||||
db_path=nextcloudregister.sqli
|
||||
captcha_timout=3600
|
@ -42,6 +42,8 @@
|
||||
<input type="password" name="password1" placeholder="Mot de passe" {% if disable %} disabled="disabled" {% endif %}/>
|
||||
<input type="password" name="password2" placeholder="Confirmez le mot de passe" {% if disable %} disabled="disabled" {% endif %}/>
|
||||
{% endif %}
|
||||
<input type="hidden" name="token" value="{{ token }}"/>
|
||||
<input type="text" name="answer" placeholder="Combien font {{first_number}} {{op_text}} {{second_number}} ?" {% if disable %} disabled="disabled" {% endif %}/>
|
||||
{% if eula %}
|
||||
<div class="eula">
|
||||
En m'inscrivant à ce service, j'accepte ses <a href="{{ eula }}">Conditions Générales d'utilisation</a>
|
||||
|
101
webapp.py
101
webapp.py
@ -1,4 +1,9 @@
|
||||
from configparser import ConfigParser
|
||||
import operator
|
||||
from os.path import exists
|
||||
import random
|
||||
from secrets import token_urlsafe
|
||||
from time import time
|
||||
|
||||
from flask import (
|
||||
Flask,
|
||||
@ -6,6 +11,8 @@ from flask import (
|
||||
render_template,
|
||||
Response,
|
||||
)
|
||||
import sqlalchemy
|
||||
import sqlalchemy.orm
|
||||
|
||||
from nextcloudregister.lib import (
|
||||
CONFIG_PATH,
|
||||
@ -24,16 +31,73 @@ config.read(CONFIG_PATH)
|
||||
app = Flask(__name__)
|
||||
base_uri = config.get("web", "base_uri", fallback="")
|
||||
base_uri = base_uri + ("" if base_uri.endswith("/") else "/")
|
||||
db_path = config.get("rules", "db_path", fallback="db.sqlite")
|
||||
Base = sqlalchemy.orm.declarative_base()
|
||||
|
||||
OPERATORS = (
|
||||
('+', operator.add),
|
||||
('×', operator.mul),
|
||||
('-', operator.sub),
|
||||
)
|
||||
|
||||
|
||||
@app.route(base_uri, methods=["GET", "POST"])
|
||||
def form_manager():
|
||||
if request.method == "POST":
|
||||
return form_post()
|
||||
else:
|
||||
return form_get()
|
||||
class Captcha(Base):
|
||||
__tablename__ = "captcha"
|
||||
|
||||
token = sqlalchemy.Column(sqlalchemy.String(90), primary_key=True)
|
||||
answer = sqlalchemy.Column(sqlalchemy.String(3))
|
||||
expiration = sqlalchemy.Column(sqlalchemy.Integer())
|
||||
|
||||
|
||||
def get_session():
|
||||
engine = sqlalchemy.create_engine(f"sqlite:///{db_path}")
|
||||
if not exists(db_path):
|
||||
Base.metadata.create_all(engine)
|
||||
session_factory = sqlalchemy.orm.sessionmaker(engine)
|
||||
return session_factory()
|
||||
|
||||
|
||||
def clean_db(session):
|
||||
session.query(Captcha).filter(Captcha.expiration < int(time())).delete()
|
||||
|
||||
|
||||
def generate_captacha():
|
||||
session = get_session()
|
||||
clean_db(session)
|
||||
first_number = random.randrange(10)
|
||||
second_number = random.randrange(10)
|
||||
op_text, op_func = random.choice(OPERATORS)
|
||||
if op_text == "-" and first_number < second_number:
|
||||
first_number, second_number = second_number, first_number
|
||||
result = op_func(first_number, second_number)
|
||||
captcha = Captcha(
|
||||
token=token_urlsafe(67),
|
||||
answer=str(result),
|
||||
expiration=int(time()) + config.getint("rules", "captcha_timout", fallback=3600),
|
||||
)
|
||||
session.add(captcha)
|
||||
session.commit()
|
||||
return {
|
||||
"first_number": first_number,
|
||||
"second_number": second_number,
|
||||
"op_text": op_text,
|
||||
"token": captcha.token,
|
||||
}
|
||||
|
||||
|
||||
def validate_captcha(token, value):
|
||||
result = False
|
||||
session = get_session()
|
||||
clean_db(session)
|
||||
captcha = session.query(Captcha).filter(Captcha.token == token).one_or_none()
|
||||
if captcha:
|
||||
result = value == captcha.answer
|
||||
session.query(Captcha).filter(Captcha.token == token).delete()
|
||||
session.commit()
|
||||
return result
|
||||
|
||||
|
||||
@app.route(base_uri, methods=["GET"])
|
||||
def form_get(data=None, error=None, info=None, success=False):
|
||||
context = {
|
||||
"base_uri": base_uri,
|
||||
@ -63,18 +127,21 @@ def form_get(data=None, error=None, info=None, success=False):
|
||||
try:
|
||||
count_accounts = api.count_accounts()
|
||||
except NextcloudApiException:
|
||||
context["max_accounts"] = 0
|
||||
context["count_accounts"] = context["max_accounts"]
|
||||
if count_accounts >= context["max_accounts"] and not success:
|
||||
context["disable"] = True
|
||||
context["error"] = (
|
||||
"Tous les comptes disponibles sur cette instance ont deja été "
|
||||
"distribués."
|
||||
)
|
||||
context["count_accounts"] = 0
|
||||
else:
|
||||
context["count_accounts"] = context["max_accounts"] - count_accounts
|
||||
context |= generate_captacha()
|
||||
return render_template("form.html", **context)
|
||||
|
||||
|
||||
@app.route(base_uri, methods=["POST"])
|
||||
def form_post():
|
||||
mandatory_email = config.getboolean(
|
||||
"rules",
|
||||
@ -86,6 +153,13 @@ def form_post():
|
||||
"mandatory_password",
|
||||
fallback=False,
|
||||
)
|
||||
# validate captcha
|
||||
if not validate_captcha(token=request.form.get("token"), value=request.form.get("answer")):
|
||||
return form_get(
|
||||
data=request.form,
|
||||
error="Le captcha est invalide."
|
||||
)
|
||||
|
||||
# validate mandatory fields
|
||||
if not request.form.get("username"):
|
||||
return form_get(
|
||||
@ -115,6 +189,19 @@ def form_post():
|
||||
)
|
||||
|
||||
api = NextcloudApi()
|
||||
try:
|
||||
if api.count_accounts() >= config.getint("rules", "max_accounts", fallback=0):
|
||||
return form_get(
|
||||
data=request.form,
|
||||
error="Tous les comptes disponibles sur cette instance ont deja été distribués."
|
||||
)
|
||||
except NextcloudApiException:
|
||||
return form_get(
|
||||
data=request.form,
|
||||
error="Tous les comptes disponibles sur cette instance ont deja été distribués."
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
api.create_account(
|
||||
username=request.form.get("username", "").strip(),
|
||||
|
Loading…
Reference in New Issue
Block a user