hébergement form, with DNS checks and form field validation
This commit is contained in:
parent
ac491fd571
commit
84d7d6334e
@ -31,6 +31,7 @@ ALLOWED_HOSTS = [
|
|||||||
'jabberfr.org',
|
'jabberfr.org',
|
||||||
'irc.jabberfr.org',
|
'irc.jabberfr.org',
|
||||||
'chat.jabberfr.org',
|
'chat.jabberfr.org',
|
||||||
|
'localhost',
|
||||||
]
|
]
|
||||||
|
|
||||||
DEFAULT_HOST = 'jabberfr'
|
DEFAULT_HOST = 'jabberfr'
|
||||||
|
31
jabberfr/templates/hebergement.html
Normal file
31
jabberfr/templates/hebergement.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{% extends "page_model.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div>
|
||||||
|
<h2>Hébergement</h2>
|
||||||
|
<p>Vous disposez d’un nom de domaine et vous souhaitez l’utiliser pour communiquer avec XMPP, mais sans gérer vous même votre serveur ?</p>
|
||||||
|
<p>Vous pouvez désormais nous déléguer l’administration de votre service XMPP !</p>
|
||||||
|
<p>Ajoutez un enregistrement <code>CNAME</code> pointant vers <code>jabberfr.org.</code> dans votre zone DNS (sans oublier le point à la fin !), et remplissez le formulaire ci-dessous :</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{% if errors %}
|
||||||
|
<p class="error">Des erreurs ont été rencontrées lors de la validation de votre demande :</p>
|
||||||
|
{% for error in errors %}
|
||||||
|
{{ error | safe }}
|
||||||
|
{% endfor %}
|
||||||
|
<p>Si vous avez du mal à faire ça, n’hésitez pas à nous demander de l’aide sur <a href="xmpp:jabberfr@chat.jabberfr.org?join">jabberfr@chat.jabberfr.org</a> (<a href="https://chat.jabberfr.org/converse.js/jabberfr@chat.jabberfr.org">webchat</a>) !</p>
|
||||||
|
{% endif %}
|
||||||
|
<form method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<p>Vous pouvez à tout moment récupérer l’intégralité des données de votre serveur, par exemple si vous souhaitez vous auto-héberger, ou passer chez un autre hébergeur.</p>
|
||||||
|
<p>N’hésitez pas à <a href="/adhesion/">adhérer à l’association</a> pour décider de l’évolution du service avec nous.</p>
|
||||||
|
</div>
|
||||||
|
<p><input type="submit" value="Envoyer !"/></p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
9
jabberfr/templates/hebergement_success.html
Normal file
9
jabberfr/templates/hebergement_success.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{% extends "page_model.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<p>Et voilà !</p>
|
||||||
|
|
||||||
|
<p>Nous allons configurer ce qu’il faut pour gérer votre domaine, nous vous enverrons un email dès que tout est en place de notre côté.</p>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -16,7 +16,7 @@ Including another URLconf
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
from jabberfr.views import get_root_index
|
from jabberfr.views import get_root_index, hebergement
|
||||||
|
|
||||||
|
|
||||||
PAGES = [
|
PAGES = [
|
||||||
@ -26,7 +26,8 @@ PAGES = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', get_root_index)
|
path('', get_root_index),
|
||||||
|
path('hébergement', hebergement),
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns += [
|
urlpatterns += [
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
from asyncio import gather, get_event_loop
|
||||||
from aiohttp import ClientSession, ClientError, ClientTimeout
|
from aiohttp import ClientSession, ClientError, ClientTimeout
|
||||||
|
from aiodns import DNSResolver
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from django import forms
|
||||||
|
from django.core.validators import RegexValidator, URLValidator
|
||||||
|
|
||||||
BASE_MUC_URL = 'http://[::1]:5280/muc_list/?'
|
BASE_MUC_URL = 'http://[::1]:5280/muc_list/?'
|
||||||
|
|
||||||
@ -10,6 +14,7 @@ TABLE_END = """
|
|||||||
</table>
|
</table>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
async def get_chatrooms(*, limit: int = 25, order: str = 'users') -> str:
|
async def get_chatrooms(*, limit: int = 25, order: str = 'users') -> str:
|
||||||
params = {
|
params = {
|
||||||
'limit': str(limit),
|
'limit': str(limit),
|
||||||
@ -47,3 +52,127 @@ async def get_chat_index(request):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return render(request, 'chat/index.html', context=context)
|
return render(request, 'chat/index.html', context=context)
|
||||||
|
|
||||||
|
|
||||||
|
class HebergForm(forms.Form):
|
||||||
|
"""Form for hosted domains"""
|
||||||
|
domain = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=True,
|
||||||
|
label='Votre nom de domaine',
|
||||||
|
validators=[
|
||||||
|
RegexValidator(
|
||||||
|
regex=URLValidator.host_re,
|
||||||
|
message='Ce nom de domaine n’est pas valide'
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
email = forms.EmailField(
|
||||||
|
required=True,
|
||||||
|
label='Votre adresse email',
|
||||||
|
)
|
||||||
|
type = forms.ChoiceField(
|
||||||
|
choices=[
|
||||||
|
('users', 'Comptes utilisateurs'),
|
||||||
|
('muc', 'Salons'),
|
||||||
|
],
|
||||||
|
label='Type d’hébergement',
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
message = forms.CharField(
|
||||||
|
widget=forms.Textarea,
|
||||||
|
max_length=3000,
|
||||||
|
label='Un petit mot ?'
|
||||||
|
)
|
||||||
|
cname = forms.BooleanField(
|
||||||
|
required=True,
|
||||||
|
label='J’ai effectué la redirection CNAME',
|
||||||
|
)
|
||||||
|
cgu = forms.BooleanField(
|
||||||
|
required=True,
|
||||||
|
label=(
|
||||||
|
'J’accepte les CGU'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def check_srv_contents(srv_client, srv_server) -> bool:
|
||||||
|
if not isinstance(srv_client, Exception): # No SRV
|
||||||
|
for srv in srv_client:
|
||||||
|
if srv.host != 'jabberfr.org' or srv.port != 5222:
|
||||||
|
return True
|
||||||
|
if not isinstance(srv_server, Exception): # No SRV
|
||||||
|
for srv in srv_server:
|
||||||
|
if srv.host != 'jabberfr.org' or srv.port != 5269:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def format_srv_errors(srv_client, srv_server) -> str:
|
||||||
|
msg = (
|
||||||
|
'<p>Vous avez des enregistrements SRV qui ne pointent pas '
|
||||||
|
'vers JabberFR:</p>\n'
|
||||||
|
)
|
||||||
|
records = []
|
||||||
|
if not isinstance(srv_client, Exception):
|
||||||
|
for srv in srv_client:
|
||||||
|
records.append(srv)
|
||||||
|
if not isinstance(srv_server, Exception):
|
||||||
|
for srv in srv_server:
|
||||||
|
records.append(srv)
|
||||||
|
text = '<pre>'
|
||||||
|
|
||||||
|
for rec in records:
|
||||||
|
text += (
|
||||||
|
f'{rec.host}. {rec.type} {rec.ttl} {rec.priority} '
|
||||||
|
f'{rec.weight} {rec.port}\n'
|
||||||
|
)
|
||||||
|
text += '</pre>'
|
||||||
|
|
||||||
|
return msg + text
|
||||||
|
|
||||||
|
|
||||||
|
async def check_dns_config(form: HebergForm) -> list[str]:
|
||||||
|
errors = []
|
||||||
|
data = form.cleaned_data
|
||||||
|
resolver = DNSResolver(loop=get_event_loop())
|
||||||
|
cname, srv_client, srv_server = await gather(
|
||||||
|
resolver.query(data['domain'], 'CNAME'),
|
||||||
|
resolver.query(f'_xmpp-server._tcp.{data["domain"]}', 'SRV'),
|
||||||
|
resolver.query(f'_xmpp-client._tcp.{data["domain"]}', 'SRV'),
|
||||||
|
return_exceptions=True,
|
||||||
|
)
|
||||||
|
if check_srv_contents(srv_client, srv_server):
|
||||||
|
errors.append(format_srv_errors(srv_client, srv_server))
|
||||||
|
if isinstance(cname, BaseException):
|
||||||
|
errors.append(
|
||||||
|
f'<p>Vous n’avez pas d’enregistrement <code>CNAME</code> pour ce'
|
||||||
|
f' domaine, ajoutez-en un qui pointe vers JabberFR :\n'
|
||||||
|
f'<pre><code>{data["domain"]} IN CNAME jabberfr.org</code></pre>'
|
||||||
|
)
|
||||||
|
elif cname.cname != 'jabberfr.org':
|
||||||
|
errors.append(
|
||||||
|
f'<p>Votre enregistrement <code>CNAME</code> ne pointe pas '
|
||||||
|
f'vers <code>jabberfr.org</code> mais vers '
|
||||||
|
f'<code>{cname.cname}</code>, vous devriez changer ça dans '
|
||||||
|
f'votre interface de gestion DNS.</p>'
|
||||||
|
)
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
async def hebergement(request):
|
||||||
|
context = {
|
||||||
|
'title': 'Hébergement chez JabberFR',
|
||||||
|
}
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = HebergForm(request.POST)
|
||||||
|
context['form'] = form
|
||||||
|
if form.is_valid():
|
||||||
|
errors = await check_dns_config(form)
|
||||||
|
if not errors:
|
||||||
|
return render(request, 'hebergement_success.html', context)
|
||||||
|
context['errors'] = errors
|
||||||
|
else:
|
||||||
|
form = HebergForm()
|
||||||
|
context['form'] = form
|
||||||
|
return render(request, 'hebergement.html', context=context)
|
||||||
|
Loading…
Reference in New Issue
Block a user