adhésion form

This commit is contained in:
Mathieu Pasquet 2021-04-18 13:24:23 +02:00
parent 803def63c3
commit 9a51821e42
8 changed files with 187 additions and 3 deletions

View File

@ -1,7 +1,7 @@
from django import forms from django import forms
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.core.validators import RegexValidator, URLValidator from django.core.validators import RegexValidator, URLValidator
from jabberfr.validators import validate_jid_userpart from jabberfr.validators import validate_jid_userpart, validate_jid
USERNAME_HELP = """ USERNAME_HELP = """
<ul> <ul>
@ -115,3 +115,45 @@ class InscriptionForm(forms.Form):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if choices: if choices:
self.fields['server'].widget.choices = choices self.fields['server'].widget.choices = choices
class AdhesionForm(forms.Form):
surname = forms.CharField(
required=True,
label="Nom de famille",
)
name = forms.CharField(
required=True,
label='Prénom',
)
email = forms.EmailField(
required=True,
label='Adresse email',
)
jid = forms.CharField(
required=True,
label='Identififant XMPP (JID)',
validators=[validate_jid],
)
captcha_id = forms.IntegerField(
required=True,
widget=forms.HiddenInput,
)
captcha = forms.CharField(
required=True,
label='Captcha',
help_text='',
)
def __init__(self, *args, **kwargs):
captcha_id, captcha_question = kwargs.pop('captcha', (0, ''))
super().__init__(*args, **kwargs)
if captcha_id and captcha_question:
self.reset_captcha(captcha_id, captcha_question)
def reset_captcha(self, captcha_id: int, question: str):
self.initial['captcha_id'] = captcha_id
self.fields['captcha_id'].initial = captcha_id
self.fields['captcha'].help_text = mark_safe(
f'\n<br/>Répondez à cette question: {question}'
)

View File

@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/3.1/ref/settings/
""" """
from pathlib import Path from pathlib import Path
from random import shuffle
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
@ -115,3 +116,15 @@ STATIC_URL = '/static/'
STATICFILES_DIRS = [ STATICFILES_DIRS = [
BASE_DIR / 'static' BASE_DIR / 'static'
] ]
# To override in local settings
CAPTCHA_QUESTIONS = [
('1 + 1?', '2'),
]
try:
from .local_settings import *
except ImportError:
pass
shuffle(CAPTCHA_QUESTIONS)

View File

@ -0,0 +1,44 @@
{% extends "page_model.html" %}
{% block content %}
<h1>Adhérez à l'association</h1>
<p>
Si vous décidez de soutenir l'association JabberFR afin de l'aider à mener ses objectifs à bien, vous pouvez adhérer ! Le but de notre association est de <strong>mettre à disposition des services de messagerie instantanée libres</strong> à travers les serveurs gérés par l'association, de <strong>promouvoir les applications et services qui y sont liés</strong>, notamment grâce au wiki, ou par la présence de ses membres à des évènements publics, et enfin, d'améliorer l'existant en <strong>développant des logiciels ou composants lorsque le besoin est ressenti</strong>.
</p>
<p>
L'adhésion à notre association suppose que vous ayez lu les <a href="http://wiki.jabberfr.org/JabberFR:Statuts">statuts de l'association</a> et que vous soyez en accord avec notre <a href="http://wiki.jabberfr.org/JabberFR:Règlement_Intérieur">règlement intérieur</a>.
</p>
<h2>Formulaire d'adhésion</h2>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<p>
<input type="submit" value="J'adhère." />
</p>
</form>
<h2>Paiement de la cotisation</h2>
<p>
<strong>Attention :</strong> pour finaliser votre adhésion et être considéré comme membre à part entière et à jour de sa cotisation, vous devez vous acquiter de la cotisation annuelle : <strong>5€</strong> pour devenir un membre actif, ou <strong>15€</strong> pour devenir un membre bienfaiteur.
</p>
<p>
Nous vous contacterons après envoi du formulaire pour vous transmettre les coordonnées bancaires de l'association. Alternativement, vous pouvez payer sur <a href="https://www.helloasso.com/associations/jabberfr">HelloAsso</a>.
</p>
<p style="font-size: 0.8em;">
<em>
Nous vous rappelons que vous disposez d'un droit d'accès, de modification, de rectification et de suppression des données qui vous concernent (art. 34 de la loi « Informatique et Libertés » du 6 janvier 1978).
</em>
</p>
{% endblock %}

View File

@ -0,0 +1,27 @@
{% extends "page_model.html" %}
{% block content %}
<h1>Adhérez à l'association</h1>
<p>Votre adhésion a été enregistrée. N\'oubliez pas de payer votre cotisation !</p>
<h2>Paiement de la cotisation</h2>
<p>
<strong>Attention :</strong> pour finaliser votre adhésion et être considéré comme membre à part entière et à jour de sa cotisation, vous devez vous acquiter de la cotisation annuelle : <strong>5€</strong> pour devenir un membre actif, ou <strong>15€</strong> pour devenir un membre bienfaiteur.
</p>
<p>
Nous vous contacterons après envoi du formulaire pour vous transmettre les coordonnées bancaires de l'association. Alternativement, vous pouvez payer sur <a href="https://www.helloasso.com/associations/jabberfr">HelloAsso</a>.
</p>
<p style="font-size: 0.8em;">
<em>
Nous vous rappelons que vous disposez d'un droit d'accès, de modification, de rectification et de suppression des données qui vous concernent (art. 34 de la loi « Informatique et Libertés » du 6 janvier 1978).
</em>
</p>
{% endblock %}

View File

@ -16,7 +16,7 @@ Including another URLconf
from django.urls import path, re_path from django.urls import path, re_path
from django.views.generic import TemplateView, RedirectView from django.views.generic import TemplateView, RedirectView
from jabberfr.views import get_root_index, hebergement, inscription from jabberfr.views import get_root_index, hebergement, inscription, adhesion
PAGES = [ PAGES = [
@ -30,6 +30,7 @@ urlpatterns = [
re_path('hébergement/?', hebergement), re_path('hébergement/?', hebergement),
re_path('hebergement/?', RedirectView.as_view(url='/hébergement')), re_path('hebergement/?', RedirectView.as_view(url='/hébergement')),
re_path('inscription/?', inscription), re_path('inscription/?', inscription),
re_path('adhesion/?', adhesion),
path('inscription/<str:domain>', inscription), path('inscription/<str:domain>', inscription),
] ]

View File

@ -1,10 +1,12 @@
import logging import logging
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from asyncio import gather, get_event_loop from asyncio import gather, get_event_loop
from random import randint
from aiodns import DNSResolver from aiodns import DNSResolver
from aiohttp import ClientSession, ClientTimeout from aiohttp import ClientSession, ClientTimeout
from django import forms from django import forms
from django.conf import settings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -113,3 +115,30 @@ def check_passwords(form: forms.Form) -> bool:
) )
return False return False
return True return True
def pick_captcha() -> tuple[str, str]:
choice = randint(0, len(settings.CAPTCHA_QUESTIONS) - 1)
question = settings.CAPTCHA_QUESTIONS[choice][0]
return str(choice), question
def validate_captcha(form: forms.Form) -> bool:
data = form.cleaned_data
print(data)
try:
captcha_id = data['captcha_id']
if captcha_id < 0 or captcha_id >= len(settings.CAPTCHA_QUESTIONS):
raise ValueError
except ValueError:
form.add_error('captcha', 'Êtes-vous un robot?')
return False
question_tup = settings.CAPTCHA_QUESTIONS[captcha_id]
if question_tup is None:
form.add_error('captcha', 'Êtes-vous un robot?')
return False
if question_tup[1] != data['captcha']:
form.add_error('captcha', 'Êtes-vous un robot?')
return False
return True

View File

@ -13,3 +13,14 @@ def validate_jid_userpart(value):
raise ValidationError( raise ValidationError(
f'"{value}" nest pas un nom dutilisateur valide.' f'"{value}" nest pas un nom dutilisateur valide.'
) )
def validate_jid(value):
try:
jid = JID(value)
if not jid.user or not jid.server:
raise InvalidJID
except InvalidJID:
raise ValidationError(
f'"{value}" nest pas un identifiant XMPP valide'
)

View File

@ -1,12 +1,14 @@
import logging import logging
from aiohttp import ClientError from aiohttp import ClientError
from django.shortcuts import render from django.shortcuts import render
from jabberfr.forms import HebergForm, InscriptionForm from jabberfr.forms import HebergForm, InscriptionForm, AdhesionForm
from jabberfr.utils import ( from jabberfr.utils import (
get_chatrooms, get_chatrooms,
get_custom_domains, get_custom_domains,
check_dns_config, check_dns_config,
check_passwords, check_passwords,
pick_captcha,
validate_captcha
) )
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -83,3 +85,18 @@ async def inscription(request, domain=None):
form = InscriptionForm(custom_choices=choices) form = InscriptionForm(custom_choices=choices)
context['form'] = form context['form'] = form
return render(request, 'inscription.html', context=context) return render(request, 'inscription.html', context=context)
async def adhesion(request):
context = {}
if request.method == 'POST':
form = AdhesionForm(request.POST)
context['form'] = form
if form.is_valid() and validate_captcha(form):
return render(request, 'adhesion_success.html', context=context)
else:
form.reset_captcha(*pick_captcha())
else:
form = AdhesionForm(captcha=pick_captcha())
context['form'] = form
return render(request, 'adhesion.html', context=context)