diff --git a/gms/memberdb/templates/thanks.html b/gms/memberdb/templates/thanks.html index ddaf5a0382173cc8effbc7f99a2dee6d12df1eb0..9f3a24f55a3ceb29dd0b6dc23f8452b88c377f53 100644 --- a/gms/memberdb/templates/thanks.html +++ b/gms/memberdb/templates/thanks.html @@ -8,4 +8,11 @@ <b>Your membership registration has been submitted.</b><br><br> Once it has been approved, you will receive an email with instructions to activate your account. {% endblock %} -{% block form %}{% endblock %} \ No newline at end of file + +{% block form %} +{% if payment_url %} +<div class="form-row readonly"> + <a class="button" title="Pay online with card, using Square payments" href="{{ payment_url }}">Pay online now</a> +</div> +{% endif %} +{% endblock %} diff --git a/gms/memberdb/urls.py b/gms/memberdb/urls.py index 82bcc9e0f45e81b43044b600408928f4e091106e..63088b9a4247eee4090f66067a1bcee4b159499c 100644 --- a/gms/memberdb/urls.py +++ b/gms/memberdb/urls.py @@ -2,24 +2,26 @@ from django.urls import path from django.contrib.auth import views as auth_views from django.views.generic.base import TemplateView -from . import views -from .views import MemberHomeView +from .views import MemberHomeView, MemberTokenView from .register import RegisterView, RenewView app_name = 'memberdb' urlpatterns = [ path('', MemberHomeView.as_view(), name='home'), path('', MemberHomeView.as_view(), name='index'), + + # use the django-provided login views with our custom templates path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'), path('logout/', auth_views.LogoutView.as_view(template_name='logout.html'), name='logout'), # override the admin login/logout views path('admin/login/', auth_views.LoginView.as_view(template_name='login.html')), path('admin/logout/', auth_views.LogoutView.as_view(template_name='logout.html')), + + # for members to "login" before having created a user account + path('login/<username>/<member_token>/', MemberTokenView.as_view(), name='login_member'), path('register/', RegisterView.as_view(), name='register'), path('renew/', RenewView.as_view(), name='renew'), - path('active/', views.getactive, name='actives'), path('thanks/', TemplateView.as_view(template_name='thanks.html'), name='thanks'), - #path('<str:username>/', views.info, name='info'), -] \ No newline at end of file +] diff --git a/gms/memberdb/views.py b/gms/memberdb/views.py index fca7b770f0013cb63c5ce2945b1300b158ff17e4..c9bac0740d555624b9082fc94f993be2fb18a582 100644 --- a/gms/memberdb/views.py +++ b/gms/memberdb/views.py @@ -1,29 +1,63 @@ from datetime import date -from django.http import HttpResponse, HttpResponseRedirect +from django.http import HttpResponse, HttpResponseRedirect, Http404 from django.shortcuts import render from django.urls import reverse from django.forms import ModelForm from django.contrib import messages +from django.views.generic.base import View from django.views.generic.edit import UpdateView -from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.auth.mixins import AccessMixin from .models import Member, IncAssocMember, Membership from .forms import MemberHomeForm -def index(request): - member_list = Member.objects.all() - context = { - 'member_list': member_list, - } - return render(request, 'index.html', context) - -def getactive(request): - actives = Membership.objects.all().select_related('member') - actives.filter(date_submitted__range=(date(2018, 1, 1), date(2018, 12, 31))) - context = { - 'member_list': actives, - } - return render(request, 'index.html', context) +class MemberMiddleware: + """ + Django middleware to get the member info from a particular session + if logged in, get member from username, otherwise store some metadata in the session thingy + see https://docs.djangoproject.com/en/2.1/topics/http/sessions/ + """ + def __init__(self, get_response): + self.get_response = get_response + # One-time configuration and initialization. + + def __call__(self, request): + # Code to be executed for each request before + # the view (and later middleware) are called. + request.member = None + + if request.user.is_authenticated: + # get the username only when a user is logged in + # note that request.user will still exist even when the user isn't logged in + request.member = Member.objects.filter(username__exact=self.request.user.username).first() + + if request.member is not None: + # clean the member's auth token because they now have a working login + request.member.token = None + request.member.save() + + # request.session is a dictionary-like object, its content is saved in the database + # and only a session ID is stored as a browser cookie (by default, but is configurable) + if 'member_id' in request.session: + # don't store member ID since we look it up by username + del request.session['member_id'] + + elif 'member_id' in request.session: + request.member = Member.objects.get(id=request.session['member_id']) + + response = self.get_response(request) + + # Code to be executed for each request/response after + # the view is called. + + return response + +class MemberAccessMixin(AccessMixin): + """Verify that the current session has a member object associated with it, or that the user is logged in""" + def dispatch(self, request, *args, **kwargs): + if (not request.user.is_authenticated) and (request.member is None): + return self.handle_no_permission() + return super().dispatch(request, *args, **kwargs) """ Can update and create models. @@ -49,7 +83,7 @@ class MyUpdateView(UpdateView): kwargs.update({'request': self.request}) return kwargs -class MemberHomeView(LoginRequiredMixin, MyUpdateView): +class MemberHomeView(MemberAccessMixin, MyUpdateView): model = Member template_name = 'home.html' form_class = MemberHomeForm @@ -67,5 +101,20 @@ class MemberHomeView(LoginRequiredMixin, MyUpdateView): def form_valid(self, form): messages.success(self.request, 'Member details updated.') - # redirect to ourselves?!! because I can't think of a less hacky way to do this + messages.warning(self.request, 'Could not update user display name in AD. Please try again once this feature has been implemented.') + + # redisplay the page + return self.get(request, *args, **kwargs) + +class MemberTokenView(View): + """ allow a user to login using a unique (secure) member token """ + def get(self, request, **kwargs): + if not ('member_token' in kwargs and 'username' in kwargs) or user.is_authenticated: + raise Http404() + + # look up the member using exact match for token and username + member = Member.objects.get(token=kwargs['member_token'], username=kwargs['username']) + if member is None: + raise Http404() + request.session['member_id'] = member.id return HttpResponseRedirect(reverse('memberdb:home'))