fix bug + add captcha
This commit is contained in:
parent
979d0079d7
commit
c96c84b836
@ -46,4 +46,7 @@ max_accounts = 50
|
|||||||
mandatory_email = yes
|
mandatory_email = yes
|
||||||
# whether or not the user must give an password to subscribe
|
# whether or not the user must give an password to subscribe
|
||||||
# at least one of email and password is mandatory
|
# 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="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 %}/>
|
<input type="password" name="password2" placeholder="Confirmez le mot de passe" {% if disable %} disabled="disabled" {% endif %}/>
|
||||||
{% 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 %}
|
{% if eula %}
|
||||||
<div class="eula">
|
<div class="eula">
|
||||||
En m'inscrivant à ce service, j'accepte ses <a href="{{ eula }}">Conditions Générales d'utilisation</a>
|
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
|
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 (
|
from flask import (
|
||||||
Flask,
|
Flask,
|
||||||
@ -6,6 +11,8 @@ from flask import (
|
|||||||
render_template,
|
render_template,
|
||||||
Response,
|
Response,
|
||||||
)
|
)
|
||||||
|
import sqlalchemy
|
||||||
|
import sqlalchemy.orm
|
||||||
|
|
||||||
from nextcloudregister.lib import (
|
from nextcloudregister.lib import (
|
||||||
CONFIG_PATH,
|
CONFIG_PATH,
|
||||||
@ -24,16 +31,73 @@ config.read(CONFIG_PATH)
|
|||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
base_uri = config.get("web", "base_uri", fallback="")
|
base_uri = config.get("web", "base_uri", fallback="")
|
||||||
base_uri = base_uri + ("" if base_uri.endswith("/") else "/")
|
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"])
|
class Captcha(Base):
|
||||||
def form_manager():
|
__tablename__ = "captcha"
|
||||||
if request.method == "POST":
|
|
||||||
return form_post()
|
token = sqlalchemy.Column(sqlalchemy.String(90), primary_key=True)
|
||||||
else:
|
answer = sqlalchemy.Column(sqlalchemy.String(3))
|
||||||
return form_get()
|
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):
|
def form_get(data=None, error=None, info=None, success=False):
|
||||||
context = {
|
context = {
|
||||||
"base_uri": base_uri,
|
"base_uri": base_uri,
|
||||||
@ -63,18 +127,21 @@ def form_get(data=None, error=None, info=None, success=False):
|
|||||||
try:
|
try:
|
||||||
count_accounts = api.count_accounts()
|
count_accounts = api.count_accounts()
|
||||||
except NextcloudApiException:
|
except NextcloudApiException:
|
||||||
context["max_accounts"] = 0
|
context["count_accounts"] = context["max_accounts"]
|
||||||
if count_accounts >= context["max_accounts"] and not success:
|
if count_accounts >= context["max_accounts"] and not success:
|
||||||
context["disable"] = True
|
context["disable"] = True
|
||||||
context["error"] = (
|
context["error"] = (
|
||||||
"Tous les comptes disponibles sur cette instance ont deja été "
|
"Tous les comptes disponibles sur cette instance ont deja été "
|
||||||
"distribués."
|
"distribués."
|
||||||
)
|
)
|
||||||
|
context["count_accounts"] = 0
|
||||||
else:
|
else:
|
||||||
context["count_accounts"] = context["max_accounts"] - count_accounts
|
context["count_accounts"] = context["max_accounts"] - count_accounts
|
||||||
|
context |= generate_captacha()
|
||||||
return render_template("form.html", **context)
|
return render_template("form.html", **context)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route(base_uri, methods=["POST"])
|
||||||
def form_post():
|
def form_post():
|
||||||
mandatory_email = config.getboolean(
|
mandatory_email = config.getboolean(
|
||||||
"rules",
|
"rules",
|
||||||
@ -86,6 +153,13 @@ def form_post():
|
|||||||
"mandatory_password",
|
"mandatory_password",
|
||||||
fallback=False,
|
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
|
# validate mandatory fields
|
||||||
if not request.form.get("username"):
|
if not request.form.get("username"):
|
||||||
return form_get(
|
return form_get(
|
||||||
@ -115,6 +189,19 @@ def form_post():
|
|||||||
)
|
)
|
||||||
|
|
||||||
api = NextcloudApi()
|
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:
|
try:
|
||||||
api.create_account(
|
api.create_account(
|
||||||
username=request.form.get("username", "").strip(),
|
username=request.form.get("username", "").strip(),
|
||||||
|
Loading…
Reference in New Issue
Block a user