Allow signup with threshold. Close #4

This commit is contained in:
Gabriel Augendre 2019-03-04 18:44:56 +01:00
parent b9355fda7d
commit 07f9e2f0e2
8 changed files with 96 additions and 8 deletions

View file

@ -160,4 +160,6 @@ CRISPY_TEMPLATE_PACK = 'bootstrap4'
LOGOUT_REDIRECT_URL = '/' LOGOUT_REDIRECT_URL = '/'
LOGIN_REDIRECT_URL = '/' LOGIN_REDIRECT_URL = '/'
USER_THRESHOLD = os.getenv('USER_THRESHOLD', 10)
django_heroku.settings(locals(), allowed_hosts=False, databases=DJANGO_ENV == 'prod') django_heroku.settings(locals(), allowed_hosts=False, databases=DJANGO_ENV == 'prod')

View file

@ -1,4 +1,5 @@
from django import forms from django import forms
from django.contrib.auth.forms import UserCreationForm
from map.models import FriendLocation, Friend from map.models import FriendLocation, Friend
@ -35,3 +36,10 @@ class LocationSharingForm(forms.ModelForm):
self.request = request self.request = request
self.fields['shares_location_to'].queryset = Friend.objects.exclude(pk=request.user.pk) self.fields['shares_location_to'].queryset = Friend.objects.exclude(pk=request.user.pk)
self.fields['shares_location_to'].label = 'Share location to' self.fields['shares_location_to'].label = 'Share location to'
class FriendCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = Friend
fields = UserCreationForm.Meta.fields

View file

@ -4,6 +4,7 @@
{% block content %} {% block content %}
{% block notice %} {% block notice %}
{% endblock %} {% endblock %}
{% block form %}
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
@ -11,4 +12,5 @@
<button type="submit" class="btn btn-primary">Save</button> <button type="submit" class="btn btn-primary">Save</button>
{% endblock %} {% endblock %}
</form> </form>
{% endblock %}
{% endblock %} {% endblock %}

View file

@ -26,6 +26,7 @@
{% endblock %} {% endblock %}
{% block form-buttons %} {% block form-buttons %}
<button type="submit" class="btn btn-primary">Save</button>
<a href="{% url 'password_change' %}" class="btn btn-secondary">Change your password</a> <a href="{% url 'password_change' %}" class="btn btn-secondary">Change your password</a>
<a href="{% url 'delete-profile' %}" class="btn btn-warning">Permanently delete your profile</a> <a href="{% url 'delete-profile' %}" class="btn btn-warning">Permanently delete your profile</a>
{% endblock %} {% endblock %}

View file

@ -9,5 +9,6 @@
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button type="submit" class="btn btn-primary">Login</button> <button type="submit" class="btn btn-primary">Login</button>
<a href="{% url 'signup' %}" class="btn btn-secondary">I don't have an account</a>
</form> </form>
{% endblock %} {% endblock %}

View file

@ -0,0 +1,48 @@
{% extends 'map/change_profile.html' %}
{% load crispy_forms_filters %}
{% block title %}Create your profile{% endblock %}
{% block h1 %}Create your profile{% endblock %}
{% block notice %}
{% if registration_disallowed %}
<div class="alert alert-warning">
<h4 class="alert-heading">Notice</h4>
<div>
Registration is currently not allowed. Thanks for your interest, please come back later.
</div>
</div>
{% else %}
<div class="alert alert-info">
<h4 class="alert-heading">Notice</h4>
<div>
The only required field is your username, which you can customize nearly freely.
If you choose to add your first and last name, they will be displayed on the map and on the right of the
navbar, at the top. If you don't, your username will be displayed instead.
<br>
Your email address will only ever be used to communicate account-related information. It will never be
sold
or used to spam you. You can choose not to communicate your email address.
</div>
<hr>
<div>
You can also permanently delete your profile using the button at the bottom of this page.
This will prompt you for confirmation about <strong>permanently</strong> and
<strong>immediately</strong>
deleting your profile, meaning that we will not be able to retrieve
your data if you change your mind.
</div>
</div>
{% endif %}
{% endblock %}
{% block form %}
{% if not registration_disallowed %}
<form method="post">
{% csrf_token %}
{{ form|crispy }}
{% block form-buttons %}
<button type="submit" class="btn btn-primary">Save</button>
{% endblock %}
</form>
{% endif %}
{% endblock %}

View file

@ -8,6 +8,7 @@ urlpatterns = [
path('add-location', views.AddLocationView.as_view(), name='add-location'), path('add-location', views.AddLocationView.as_view(), name='add-location'),
path('delete-location', views.DeleteLocationView.as_view(), name='delete-location'), path('delete-location', views.DeleteLocationView.as_view(), name='delete-location'),
path('share-location', views.LocationSharingView.as_view(), name='share-location'), path('share-location', views.LocationSharingView.as_view(), name='share-location'),
path('accounts/signup', views.SignupView.as_view(), name='signup'),
path('accounts/profile', views.UpdateProfileView.as_view(), name='change-profile'), path('accounts/profile', views.UpdateProfileView.as_view(), name='change-profile'),
path('accounts/profile/delete', views.DeleteProfileView.as_view(), name='delete-profile'), path('accounts/profile/delete', views.DeleteProfileView.as_view(), name='delete-profile'),
] ]

View file

@ -1,11 +1,13 @@
from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.views import generic from django.views import generic
from map import models from map import models
from map.forms import LocationForm, LocationSharingForm from map.forms import LocationForm, LocationSharingForm, FriendCreationForm
from map.mixins import QuickActionsMixin from map.mixins import QuickActionsMixin
from map.models import Friend
class MapView(LoginRequiredMixin, QuickActionsMixin, generic.DetailView): class MapView(LoginRequiredMixin, QuickActionsMixin, generic.DetailView):
@ -111,6 +113,29 @@ class DeleteLocationView(LoginRequiredMixin, generic.DeleteView):
return super().get_success_url() return super().get_success_url()
class SignupView(generic.CreateView):
model = models.Friend
template_name = 'registration/signup.html'
success_url = reverse_lazy('login')
form_class = FriendCreationForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['registration_disallowed'] = Friend.objects.count() >= settings.USER_THRESHOLD
return context
def post(self, request, *args, **kwargs):
if Friend.objects.count() >= settings.USER_THRESHOLD:
raise Exception('No more users allowed')
return super().post(request, *args, **kwargs)
def get_success_url(self):
self.object.is_active = False
self.object.save()
messages.success(self.request, 'Your profile has been successfully created, wait for approval.')
return super().get_success_url()
class UpdateProfileView(LoginRequiredMixin, QuickActionsMixin, generic.UpdateView): class UpdateProfileView(LoginRequiredMixin, QuickActionsMixin, generic.UpdateView):
model = models.Friend model = models.Friend
context_object_name = 'friend' context_object_name = 'friend'