Parcourir la source

Merge branch 'registration'

Jocelyn Delalande il y a 6 ans
Parent
commit
545b7f675b

+ 5 - 1
README.md

@@ -50,7 +50,7 @@ Install dependencies. On Debian, you will probably need the
 `python-dev`, `python-pip`, `libldap-dev`, `libpq-dev`, `libsasl2-dev`,
 `python-dev`, `python-pip`, `libldap-dev`, `libpq-dev`, `libsasl2-dev`,
 and `libjpeg-dev` packages.
 and `libjpeg-dev` packages.
 
 
-    sudo apt-get install python-dev python-pip libldap2-dev libpq-dev libsasl2-dev libjpeg-dev libxml2-dev libxslt1-dev libffi-dev
+    sudo apt-get install python-dev python-pip libldap2-dev libpq-dev libsasl2-dev libjpeg-dev libxml2-dev libxslt1-dev libffi-dev python-cairo libpango1.0-0
 
 
 You need a recent *pip* for the installation of dependencies to work. If you
 You need a recent *pip* for the installation of dependencies to work. If you
 don't meet that requirement (Ubuntu trusty does not), run:
 don't meet that requirement (Ubuntu trusty does not), run:
@@ -340,6 +340,10 @@ List of available settings in your `settings_local.py` file.
 - `LDAP_ACTIVATE`: See *LDAP*
 - `LDAP_ACTIVATE`: See *LDAP*
 - `MEMBER_MEMBERSHIP_INFO_URL`: Link to a page with information on how to become a member or pay the membership fee
 - `MEMBER_MEMBERSHIP_INFO_URL`: Link to a page with information on how to become a member or pay the membership fee
 - `SUBSCRIPTION_REFERENCE`: Pattern used to display a unique reference for any subscription. Helpful for bank wire transfer identification
 - `SUBSCRIPTION_REFERENCE`: Pattern used to display a unique reference for any subscription. Helpful for bank wire transfer identification
+- `REGISTRATION_OPEN` : Allow visitor to join the association by register on COIN
+- `ACCOUNT_ACTIVATION_DAYS` : All account with unvalidated email will be deleted after X days
+- `MEMBERSHIP_REFERENCE` : Template string to display the label the member should indicates for the bank transfer, default: "ADH-{{ user.pk }}"
+- `DEFAULT_MEMBERSHIP_FEE` : Default membership fee, if you have a more complex membership fees policy, you could overwrite templates
 - `PAYMENT_DELAY`: Payment delay in days for issued invoices ( default is 30 days which is the default in french law)
 - `PAYMENT_DELAY`: Payment delay in days for issued invoices ( default is 30 days which is the default in french law)
 - `MEMBER_CAN_EDIT_PROFILE`: Allow members to edit their profiles
 - `MEMBER_CAN_EDIT_PROFILE`: Allow members to edit their profiles
 - `HANDLE_BALANCE`: Allows to handle money balances for members (False default)
 - `HANDLE_BALANCE`: Allows to handle money balances for members (False default)

+ 2 - 3
coin/billing/views.py

@@ -3,7 +3,7 @@ from __future__ import unicode_literals
 
 
 from django.http import HttpResponse, HttpResponseRedirect
 from django.http import HttpResponse, HttpResponseRedirect
 from django.template import RequestContext
 from django.template import RequestContext
-from django.shortcuts import render, render_to_response
+from django.shortcuts import render
 from django.contrib import messages
 from django.contrib import messages
 
 
 from sendfile import sendfile
 from sendfile import sendfile
@@ -44,7 +44,6 @@ def invoice(request, id):
 
 
     assert_user_can_view_the_invoice(request, invoice)
     assert_user_can_view_the_invoice(request, invoice)
 
 
-    return render_to_response('billing/invoice.html', {"invoice": invoice},
-                              context_instance=RequestContext(request))
+    return render(request, 'billing/invoice.html', {"invoice": invoice})
 
 
     return response
     return response

+ 40 - 0
coin/members/forms.py

@@ -4,9 +4,49 @@ from __future__ import unicode_literals
 from django import forms
 from django import forms
 from django.contrib.auth.forms import PasswordResetForm, ReadOnlyPasswordHashField
 from django.contrib.auth.forms import PasswordResetForm, ReadOnlyPasswordHashField
 from django.forms.utils import ErrorList
 from django.forms.utils import ErrorList
+from django.forms.forms import BoundField
 
 
 from coin.members.models import Member
 from coin.members.models import Member
 
 
+from registration.forms import RegistrationForm
+
+
+class MemberRegistrationForm(RegistrationForm):
+    # Protect against robot
+    trap = forms.CharField(required=False, label='Trap',
+            widget=forms.TextInput(attrs={'style' : 'display:none'}),
+        help_text="Si vous êtes humain ignorez ce champ")
+
+    def __init__(self, *args, **kwargs):
+        super(MemberRegistrationForm, self).__init__(*args, **kwargs)
+
+        for fieldname in ['email', 'organization_name', 'password2']:
+            self.fields[fieldname].help_text = None
+
+    def is_valid(self):
+         valid = super(MemberRegistrationForm,self).is_valid()
+         avoid_trap = not self.data['trap']
+         if valid and avoid_trap:
+             return True
+         else:
+             return False
+
+    def as_p(self):
+        """"
+        We rewrite the as_p method to apply a style on the <p> tag related to
+        trap field. Indeed, it seeems there is no cleaner way to do it.
+        """
+        def css_classes(self, extra_classes=None):
+            return 'captcha'
+
+        func_type = type(BoundField.css_classes)
+        self['trap'].css_classes = func_type(css_classes, self, BoundField)
+        return super(MemberRegistrationForm, self).as_p()
+
+    class Meta:
+        model = Member
+        fields = ['type', 'first_name', 'last_name',
+                  'organization_name', 'email', 'username', 'trap']
 
 
 class MemberCreationForm(forms.ModelForm):
 class MemberCreationForm(forms.ModelForm):
 
 

+ 1 - 1
coin/members/migrations/0003_auto_20141007_0956.py

@@ -14,7 +14,7 @@ class Migration(migrations.Migration):
         migrations.AlterField(
         migrations.AlterField(
             model_name='membershipfee',
             model_name='membershipfee',
             name='amount',
             name='amount',
-            field=models.IntegerField(default=settings.MEMBER_DEFAULT_COTISATION, help_text='en \u20ac', verbose_name='montant'),
+            field=models.IntegerField(default=settings.DEFAULT_MEMBERSHIP_FEE, help_text='en \u20ac', verbose_name='montant'),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
             model_name='membershipfee',
             model_name='membershipfee',

+ 1 - 1
coin/members/migrations/0004_auto_20141007_1002.py

@@ -15,6 +15,6 @@ class Migration(migrations.Migration):
         migrations.AlterField(
         migrations.AlterField(
             model_name='membershipfee',
             model_name='membershipfee',
             name='amount',
             name='amount',
-            field=models.DecimalField(default=settings.MEMBER_DEFAULT_COTISATION, help_text='en \u20ac', verbose_name='montant', max_digits=5, decimal_places=2),
+            field=models.DecimalField(default=settings.DEFAULT_MEMBERSHIP_FEE, help_text='en \u20ac', verbose_name='montant', max_digits=5, decimal_places=2),
         ),
         ),
     ]
     ]

+ 9 - 4
coin/members/models.py

@@ -45,10 +45,15 @@ class Member(CoinLdapSyncMixin, AbstractUser):
         ('natural_person', 'Personne physique'),
         ('natural_person', 'Personne physique'),
         ('legal_entity', 'Personne morale'),
         ('legal_entity', 'Personne morale'),
     )
     )
+
+    MEMBER_STATUS_MEMBER = 'member'
+    MEMBER_STATUS_NOT_MEMBER = 'not_member'
+    MEMBER_STATUS_PENDING = 'pending'
+
     MEMBER_STATUS_CHOICES = (
     MEMBER_STATUS_CHOICES = (
-        ('member', 'Adhérent'),
-        ('not_member', 'Non adhérent'),
-        ('pending', "Demande d'adhésion"),
+        (MEMBER_STATUS_MEMBER, 'Adhérent'),
+        (MEMBER_STATUS_NOT_MEMBER, 'Non adhérent'),
+        (MEMBER_STATUS_PENDING, "Demande d'adhésion"),
     )
     )
 
 
     status = models.CharField(max_length=50, choices=MEMBER_STATUS_CHOICES,
     status = models.CharField(max_length=50, choices=MEMBER_STATUS_CHOICES,
@@ -430,7 +435,7 @@ class MembershipFee(models.Model):
     member = models.ForeignKey('Member', related_name='membership_fees',
     member = models.ForeignKey('Member', related_name='membership_fees',
                                verbose_name='membre')
                                verbose_name='membre')
     amount = models.DecimalField(null=False, max_digits=5, decimal_places=2,
     amount = models.DecimalField(null=False, max_digits=5, decimal_places=2,
-                                 default=settings.MEMBER_DEFAULT_COTISATION,
+                                 default=settings.DEFAULT_MEMBERSHIP_FEE,
                                  verbose_name='montant', help_text='en €')
                                  verbose_name='montant', help_text='en €')
     start_date = models.DateField(
     start_date = models.DateField(
         null=False,
         null=False,

+ 21 - 0
coin/members/registration_views.py

@@ -0,0 +1,21 @@
+from registration.backends.hmac.views import ActivationView, RegistrationView
+
+
+class MemberActivationView(ActivationView):
+    template_name = 'members/registration/activate.html'
+    def get_success_url(self, user):
+        return ('members:registration_activation_complete', (), {})
+
+class MemberRegistrationView(RegistrationView):
+    success_url = ('member:registration_activation_complete', (), {})
+    email_subject_template = 'members/registration/activation_email_subject.txt'
+    email_body_template = 'members/registration/activation_email.txt'
+    template_name = 'members/registration/registration_form.html'
+
+    def register(self, form):
+        new_user = super(MemberRegistrationView, self).register(form)
+        new_user.status = new_user.MEMBER_STATUS_PENDING
+        return new_user.save()
+
+    def get_success_url(self, user):
+        return ('members:registration_complete', (), {})

+ 8 - 0
coin/members/templates/members/registration/activate.html

@@ -0,0 +1,8 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+<p>L'activation de votre compte a échoué ou ce dernier a déjà été activé.</p>
+
+{% endblock %}

+ 18 - 0
coin/members/templates/members/registration/activation_complete.html

@@ -0,0 +1,18 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+<h2>Compte adhérent créé</h2>
+{% if dues %}
+    <p>Votre compte adhérent est désormais créé, pour finaliser votre adhésion merci d'<b>envoyer votre adhésion de {{ dues }} €</b> par virement  avec le libellé suivant:&nbsp;<b>{{ bank_transfer_label }}</b> .</p>
+
+    <h2>Coordonnées bancaires</h2>
+    <div id="payment-howto" class="panel">
+        {% include "billing/payment_howto.html" %}
+    </div>
+{% else %}
+    <p>Votre compte adhérent est désormais créé.</p>
+{% endif %}
+
+{% endblock %}

+ 12 - 0
coin/members/templates/members/registration/activation_email.txt

@@ -0,0 +1,12 @@
+{% load i18n %}
+Bonjour,
+
+Pour activer votre compte adhérent {{ site.name }}, merci de suivre le lien suivant:
+
+http://{{ site.domain }}{% url 'members:registration_activate' activation_key %}
+
+{% blocktrans %}Ce lien sera valable pendant {{ expiration_days }} jours.{% endblocktrans %}
+
+Ceci est un courriel automatique envoyé à la suite d'une demande de créayion de compte.
+
+L'équipe de l'association {{ branding.shortname|capfirst }}

+ 1 - 0
coin/members/templates/members/registration/activation_email_subject.txt

@@ -0,0 +1 @@
+{% load i18n %}Activation de votre compte adhérent {{ site.name }}

+ 11 - 4
coin/members/templates/members/registration/login.html

@@ -39,14 +39,21 @@
             <input type="submit" value="Connexion" class="button radius"/>
             <input type="submit" value="Connexion" class="button radius"/>
             <input type="hidden" name="next" value="{{ next }}" />
             <input type="hidden" name="next" value="{{ next }}" />
             <a id="password-reset-link" href="{% url 'members:password_reset' %}" tabindex="100">Mot de passe oublié ?</a>
             <a id="password-reset-link" href="{% url 'members:password_reset' %}" tabindex="100">Mot de passe oublié ?</a>
+            {% if settings.REGISTRATION_OPEN  %}
+                / <a href="{% url 'members:registration_register' %}">Créer un compte</a>
+            {% endif %}
         </form>
         </form>
     </div>
     </div>
     <div class="medium-5 columns">
     <div class="medium-5 columns">
         <div class="panel callout" id="newcomers">
         <div class="panel callout" id="newcomers">
-            <h3>Nouvel adhérent ?</h3>
-            <p>Pour votre première connexion, il faut définir votre mot de passe.<br />
-            <a href="{% url 'members:password_reset' %}"><i class="fa fa-arrow-right"></i>
- Initialiser mon mot de passe</a></p>
+                {% if not settings.REGISTRATION_OPEN  %}
+                    <h3>Nouvel adhérent⋅e ?</h3>
+                    <p>Pour votre première connexion, il faut définir votre mot de passe.<br />
+                {% else %}
+                    <h3>Première connexion</h3>
+                    <p>Si un·e bénévole a déjà créé votre compte, il faut commencer par choisir votre mot de passe.<br />
+                {% endif %}
+                <a href="{% url 'members:password_reset' %}"><i class="fa fa-arrow-right"></i> Initialiser mon mot de passe</a></p>
         </div>
         </div>
     </div>
     </div>
 
 

+ 6 - 0
coin/members/templates/members/registration/registration_closed.html

@@ -0,0 +1,6 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+	<p>{% trans "Registration is currently closed." %}</p>
+{% endblock %}

+ 6 - 0
coin/members/templates/members/registration/registration_complete.html

@@ -0,0 +1,6 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+<p>Votre demande de création de compte a été enregistrée. Afin de finaliser la création du compte, un email d'activation vous a été envoyé.</p>
+{% endblock %}

+ 65 - 0
coin/members/templates/members/registration/registration_form.html

@@ -0,0 +1,65 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+        <h2>Créer un compte adhérent</h2>
+<div class="row">
+    <div class="medium-4 large-4 columns">
+        <div class="panel callout">
+            <h3>Déjà un compte ?</h3>
+            <p>Il est possible qu'un bénévole ait déjà créé votre compte.</p><p>Dans ce cas pour votre première connexion, il faut commencer par choisir votre mot de passe.<br />
+            <a href="{% url 'members:password_reset' %}"><i class="fa fa-arrow-right"></i> Initialiser mon mot de passe</a></p>
+        
+        <a href="{% url 'members:login' %}"><i class="fa fa-arrow-right"></i> OU essayer de me connecter</a>
+        </div>
+    </div>
+
+    <div class="medium-8 large-8 columns">
+        <form method="post" action=".">
+        
+            {% csrf_token %}
+            <fieldset class="module aligned wide">
+            {{ form.as_p }}
+            </fieldset>
+        <input type="submit" class="button radius" value="Créer mon compte" />
+        </form>
+    </div>
+</div>
+{% endblock %}
+{% block extra_js %}
+<script>
+$(document).ready(function () {
+  var hideFields=function(){
+    var optionSelected = $("option:selected", this);
+    var valueSelected = this.value;
+    if (valueSelected == 'legal_entity') {
+      $('#id_first_name').parent().hide();
+      $('#id_last_name').parent().hide();
+      $('#id_organization_name').parent().show();
+      $('#id_first_name').val('');
+      $('#id_last_name').val('');
+    } else if (valueSelected == 'natural_person') {
+      $('#id_organization_name').parent().hide();
+      $('#id_first_name').parent().show();
+      $('#id_last_name').parent().show();
+      $('#id_organization_name').val('');
+    }
+    return false;
+  };
+  $('#id_type').on('change', hideFields);
+  if (!$('#id_organization_name').val()) {
+    $('#id_type').val('natural_person');
+      $('#id_organization_name').parent().hide();
+      $('#id_first_name').parent().show();
+      $('#id_last_name').parent().show();
+  }
+  else {
+    $('#id_type').val('legal_entity');
+      $('#id_first_name').parent().hide();
+      $('#id_last_name').parent().hide();
+      $('#id_organization_name').parent().show();
+  }
+});
+</script>
+
+{% endblock %}

+ 44 - 3
coin/members/urls.py

@@ -2,16 +2,29 @@
 from __future__ import unicode_literals
 from __future__ import unicode_literals
 
 
 from django.conf.urls import patterns, url
 from django.conf.urls import patterns, url
-from django.views.generic import DetailView
+from coin.members import forms
 from coin.members import views
 from coin.members import views
-from coin.members.models import Member
+from django.views.generic.base import TemplateView
+from . import registration_views as views_r
+from coin import settings
 
 
+from registration.signals import user_activated
+from django.contrib.auth import login
+
+def login_on_activation(sender, user, request, **kwargs):
+    """Logs in the user after activation"""
+    user.backend = 'django.contrib.auth.backends.ModelBackend'
+    login(request, user)
+
+# Registers the function with the django-registration user_activated signal
+user_activated.connect(login_on_activation)
 
 
 urlpatterns = patterns(
 urlpatterns = patterns(
     '',
     '',
     url(r'^$', views.index, name='index'),
     url(r'^$', views.index, name='index'),
     url(r'^login/$', 'django.contrib.auth.views.login',
     url(r'^login/$', 'django.contrib.auth.views.login',
-        {'template_name': 'members/registration/login.html'},
+        {'template_name': 'members/registration/login.html',
+         'extra_context': {'settings': settings} },
         name='login'),
         name='login'),
     url(r'^logout/$', 'django.contrib.auth.views.logout_then_login',
     url(r'^logout/$', 'django.contrib.auth.views.logout_then_login',
         name='logout'),
         name='logout'),
@@ -43,6 +56,34 @@ urlpatterns = patterns(
         name='password_reset_complete'),
         name='password_reset_complete'),
 
 
 
 
+    url(r'^activate/complete/$', views.activation_completed,
+        name='registration_activation_complete'),
+    # The activation key can make use of any character from the
+    # URL-safe base64 alphabet, plus the colon as a separator.
+    url(r'^activate/(?P<activation_key>[-:\w]+)/$',
+        views_r.MemberActivationView.as_view(),
+        name='registration_activate'),
+    url(r'^register/$',
+        views_r.MemberRegistrationView.as_view(
+            form_class=forms.MemberRegistrationForm,
+            template_name='members/registration/registration_form.html'
+        ),
+        name='registration_register'),
+    url(r'^register/complete/$',
+        TemplateView.as_view(
+            template_name='members/registration/registration_complete.html'
+        ),
+        name='registration_complete'),
+    url(r'^register/closed/$',
+        TemplateView.as_view(
+            template_name='members/registration/registration_closed.html'
+        ),
+        name='registration_disallowed'),
+    #url(r'', include('registration.auth_urls')),
+
+
+
+
     url(r'^detail/$', views.detail,
     url(r'^detail/$', views.detail,
         name='detail'),
         name='detail'),
 
 

+ 24 - 17
coin/members/views.py

@@ -2,18 +2,16 @@
 from __future__ import unicode_literals
 from __future__ import unicode_literals
 
 
 from django.template import RequestContext
 from django.template import RequestContext
-from django.shortcuts import render_to_response, render
+from django.shortcuts import render
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.decorators import login_required
-from django.http import Http404
 from django.conf import settings
 from django.conf import settings
 from forms import PersonMemberChangeForm, OrganizationMemberChangeForm
 from forms import PersonMemberChangeForm, OrganizationMemberChangeForm
 
 
 @login_required
 @login_required
 def index(request):
 def index(request):
     has_isp_feed = 'isp' in [k for k, _, _ in settings.FEEDS]
     has_isp_feed = 'isp' in [k for k, _, _ in settings.FEEDS]
-    return render_to_response('members/index.html',
-                              {'has_isp_feed': has_isp_feed},
-                              context_instance=RequestContext(request))
+    return render(request, 'members/index.html',
+                  {'has_isp_feed': has_isp_feed})
 
 
 
 
 @login_required
 @login_required
@@ -47,10 +45,9 @@ def subscriptions(request):
     subscriptions = request.user.get_active_subscriptions()
     subscriptions = request.user.get_active_subscriptions()
     old_subscriptions = request.user.get_inactive_subscriptions()
     old_subscriptions = request.user.get_inactive_subscriptions()
 
 
-    return render_to_response('members/subscriptions.html',
-                              {'subscriptions': subscriptions,
-                               'old_subscriptions': old_subscriptions},
-                              context_instance=RequestContext(request))
+    return render(request, 'members/subscriptions.html',
+                  {'subscriptions': subscriptions,
+                   'old_subscriptions': old_subscriptions})
 
 
 
 
 @login_required
 @login_required
@@ -59,15 +56,25 @@ def invoices(request):
     invoices = request.user.invoices.filter(validated=True).order_by('-date')
     invoices = request.user.invoices.filter(validated=True).order_by('-date')
     payments = request.user.payments.filter().order_by('-date')
     payments = request.user.payments.filter().order_by('-date')
 
 
-    return render_to_response('members/invoices.html',
-                              {'balance' : balance, 
-                               'handle_balance' : settings.HANDLE_BALANCE, 
-                               'invoices': invoices, 
-                               'payments': payments},
-                              context_instance=RequestContext(request))
+    return render(request, 'members/invoices.html',
+                              {'balance' : balance,
+                               'handle_balance' : settings.HANDLE_BALANCE,
+                               'invoices': invoices,
+                               'payments': payments})
 
 
 
 
 @login_required
 @login_required
 def contact(request):
 def contact(request):
-    return render_to_response('members/contact.html',
-                              context_instance=RequestContext(request))
+    return render(request, 'members/contact.html')
+
+
+@login_required
+def activation_completed(request):
+    label_template = settings.MEMBERSHIP_REFERENCE.format(user=request.user)
+    context = {
+        'bank_transfer_label': label_template,
+        'dues': settings.DEFAULT_MEMBERSHIP_FEE
+    }
+
+    return render(request, 'members/registration/activation_complete.html',
+                  context)

+ 2 - 0
coin/mixins.py

@@ -4,6 +4,8 @@ from __future__ import unicode_literals
 from django.db import transaction
 from django.db import transaction
 from django.conf import settings
 from django.conf import settings
 
 
+from django.views.generic import TemplateView
+
 
 
 class CoinLdapSyncMixin(object):
 class CoinLdapSyncMixin(object):
 
 

+ 12 - 1
coin/settings_base.py

@@ -246,7 +246,7 @@ VPN_CONF_BASE_DN = None
 
 
 # Membership configuration
 # Membership configuration
 # Default cotisation in €, per year
 # Default cotisation in €, per year
-MEMBER_DEFAULT_COTISATION = 20
+DEFAULT_MEMBERSHIP_FEE = 20
 
 
 # Link to a page with information on how to become a member or pay the
 # Link to a page with information on how to become a member or pay the
 # membership fee
 # membership fee
@@ -256,6 +256,10 @@ MEMBER_MEMBERSHIP_INFO_URL = ''
 # Helpful for bank wire transfer identification
 # Helpful for bank wire transfer identification
 SUBSCRIPTION_REFERENCE = 'REF-{subscription.offer.reference}-{subscription.pk}'
 SUBSCRIPTION_REFERENCE = 'REF-{subscription.offer.reference}-{subscription.pk}'
 
 
+# Template string to display the label the member should indicates for the bank
+# transfer
+MEMBERSHIP_REFERENCE = "ADH-{user.pk}"
+
 # Payment delay in days
 # Payment delay in days
 PAYMENT_DELAY = 30
 PAYMENT_DELAY = 30
 
 
@@ -270,6 +274,13 @@ FEEDS = (
 #    ('isp', 'http://isp.example.com/feed/', 3),
 #    ('isp', 'http://isp.example.com/feed/', 3),
 )
 )
 
 
+# Account registration
+# Allow visitor to join the association by register on COIN
+REGISTRATION_OPEN = False
+
+# All account with unvalidated email will be deleted after X days
+ACCOUNT_ACTIVATION_DAYS = 7
+
 # Member can edit their own data
 # Member can edit their own data
 MEMBER_CAN_EDIT_PROFILE = False
 MEMBER_CAN_EDIT_PROFILE = False
 
 

+ 5 - 0
coin/static/css/local.css

@@ -420,3 +420,8 @@ form .helptext {
 .list-filter {
 .list-filter {
 	text-align: right;
 	text-align: right;
 }
 }
+
+/* Registration */
+.captcha {
+    display:none;
+}

+ 3 - 4
coin/views.py

@@ -6,7 +6,7 @@ import HTMLParser
 
 
 from django.views.decorators.cache import cache_page
 from django.views.decorators.cache import cache_page
 from django.template import RequestContext
 from django.template import RequestContext
-from django.shortcuts import render_to_response
+from django.shortcuts import render
 from django.http import HttpResponse, HttpResponseNotFound, HttpResponseServerError
 from django.http import HttpResponse, HttpResponseNotFound, HttpResponseServerError
 from django.conf import settings
 from django.conf import settings
 
 
@@ -36,8 +36,7 @@ def feed(request, feed_name):
         feed = feedparser.parse(feed_url)
         feed = feedparser.parse(feed_url)
         entries = feed.entries[:limit]
         entries = feed.entries[:limit]
 
 
-        return render_to_response('fragments/feed.html',
-                                  {'feed_entries': entries},
-                                  context_instance=RequestContext(request))
+        return render(request, 'fragments/feed.html',
+                                  {'feed_entries': entries})
     except:
     except:
         return HttpResponseServerError('')
         return HttpResponseServerError('')

+ 1 - 1
contrib/ansible/coin-customizations/django_local_settings.py.j2

@@ -27,7 +27,7 @@ STATIC_ROOT = '{{ www_static_assets_directory }}'
 #EMAIL_USE_TLS = True
 #EMAIL_USE_TLS = True
 #EMAIL_HOST = "localhost"
 #EMAIL_HOST = "localhost"
 
 
-MEMBER_DEFAULT_COTISATION = 16
+DEFAULT_MEMBERSHIP_FEE = 16
 
 
 FEEDS = (
 FEEDS = (
           #('isp', 'https://faimaison.net/feeds/all.atom.xml', 3),
           #('isp', 'https://faimaison.net/feeds/all.atom.xml', 3),

+ 1 - 0
requirements.txt

@@ -16,5 +16,6 @@ feedparser
 six==1.10.0
 six==1.10.0
 WeasyPrint==0.31
 WeasyPrint==0.31
 freezegun==0.3.8
 freezegun==0.3.8
+django-registration==2.2
 pytz>=2018.5
 pytz>=2018.5
 unidecode>=1.0,<1.1
 unidecode>=1.0,<1.1

+ 1 - 1
vpn/views.py

@@ -5,7 +5,7 @@ import os
 import urllib2
 import urllib2
 
 
 from django.http import StreamingHttpResponse, HttpResponseServerError
 from django.http import StreamingHttpResponse, HttpResponseServerError
-from django.shortcuts import render_to_response, get_object_or_404
+from django.shortcuts import get_object_or_404
 from django.views.generic.detail import DetailView
 from django.views.generic.detail import DetailView
 from django.views.generic.edit import UpdateView
 from django.views.generic.edit import UpdateView
 from django.conf import settings
 from django.conf import settings