diff --git a/jabberfr/settings.py b/jabberfr/settings.py index d412e93..858496c 100644 --- a/jabberfr/settings.py +++ b/jabberfr/settings.py @@ -31,6 +31,7 @@ ALLOWED_HOSTS = [ 'jabberfr.org', 'irc.jabberfr.org', 'chat.jabberfr.org', + 'localhost', ] DEFAULT_HOST = 'jabberfr' diff --git a/jabberfr/templates/hebergement.html b/jabberfr/templates/hebergement.html new file mode 100644 index 0000000..15cb5b8 --- /dev/null +++ b/jabberfr/templates/hebergement.html @@ -0,0 +1,31 @@ +{% extends "page_model.html" %} + +{% block content %} +
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 ?
+Vous pouvez désormais nous déléguer l’administration de votre service XMPP !
+Ajoutez un enregistrement CNAME
pointant vers jabberfr.org.
dans votre zone DNS (sans oublier le point à la fin !), et remplissez le formulaire ci-dessous :
Des erreurs ont été rencontrées lors de la validation de votre demande :
+ {% for error in errors %} +{{ error | safe }} + {% endfor %} +Si vous avez du mal à faire ça, n’hésitez pas à nous demander de l’aide sur jabberfr@chat.jabberfr.org (webchat) !
+{% endif %} +Et voilà !
+ +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é.
+ +{% endblock %} diff --git a/jabberfr/urls.py b/jabberfr/urls.py index 054aa02..b6bbc56 100644 --- a/jabberfr/urls.py +++ b/jabberfr/urls.py @@ -16,7 +16,7 @@ Including another URLconf from django.urls import path from django.views.generic import TemplateView -from jabberfr.views import get_root_index +from jabberfr.views import get_root_index, hebergement PAGES = [ @@ -26,7 +26,8 @@ PAGES = [ ] urlpatterns = [ - path('', get_root_index) + path('', get_root_index), + path('hébergement', hebergement), ] urlpatterns += [ diff --git a/jabberfr/views.py b/jabberfr/views.py index 96bebdf..9605b6e 100644 --- a/jabberfr/views.py +++ b/jabberfr/views.py @@ -1,5 +1,9 @@ +from asyncio import gather, get_event_loop from aiohttp import ClientSession, ClientError, ClientTimeout +from aiodns import DNSResolver from django.shortcuts import render +from django import forms +from django.core.validators import RegexValidator, URLValidator BASE_MUC_URL = 'http://[::1]:5280/muc_list/?' @@ -10,6 +14,7 @@ TABLE_END = """ """ + async def get_chatrooms(*, limit: int = 25, order: str = 'users') -> str: params = { 'limit': str(limit), @@ -47,3 +52,127 @@ async def get_chat_index(request): } 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 = ( + 'Vous avez des enregistrements SRV qui ne pointent pas ' + 'vers JabberFR:
\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 = '' + + for rec in records: + text += ( + f'{rec.host}. {rec.type} {rec.ttl} {rec.priority} ' + f'{rec.weight} {rec.port}\n' + ) + text += '' + + 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'
Vous n’avez pas d’enregistrement CNAME
pour ce'
+ f' domaine, ajoutez-en un qui pointe vers JabberFR :\n'
+ f'
{data["domain"]} IN CNAME jabberfr.org
'
+ )
+ elif cname.cname != 'jabberfr.org':
+ errors.append(
+ f'Votre enregistrement CNAME
ne pointe pas '
+ f'vers jabberfr.org
mais vers '
+ f'{cname.cname}
, vous devriez changer ça dans '
+ f'votre interface de gestion DNS.