# Society Self-Service # Copyright © 2018-2019 Yingtong Li (RunasSudo) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . from ratelimit.decorators import ratelimit from django.contrib.auth.decorators import login_required from django.conf import settings from django.db import transaction from django.http import HttpResponse from django.shortcuts import render, redirect from django.urls import reverse from django.utils import timezone from . import monboard from . import models @login_required def index(request): try: member = models.Member.objects.get(email=request.user.email) except models.Member.DoesNotExist: member = None return render(request, 'ssmembership/index.html', {'member': member, 'years': models.Member.YEARS}) if request.method != 'POST': return render(request, 'ssmembership/index.html', {'member': member, 'years': models.Member.YEARS}) # Update membership member.student_id = request.POST['student_id'] member.first_name = request.POST['first_name'] member.last_name = request.POST['last_name'] member.phone = request.POST['phone'] member.year = int(request.POST['year']) member.is_msa = True if request.POST['is_msa'] == '1' else '0' errors = member.validation_problems() if not member or len(errors) > 0: return render(request, 'ssmembership/index.html', { 'member': member, 'years': models.Member.YEARS, 'errors': errors }) member.save() # Update bulletin if 'sspromotions' in settings.INSTALLED_APPS: import sspromotions.models sspromotions.models.BulletinSubscription.set_member_subscribed(member, True if request.POST['bulletin_subscribe'] == '1' else False) for group in sspromotions.models.Group.objects.filter(subscribable=True).all(): if ('bulletin_group_' + str(group.id)) in request.POST and request.POST['bulletin_group_' + str(group.id)]: group.subscribe_member(member, True) else: group.subscribe_member(member, False) return render(request, 'ssmembership/index.html', {'member': member, 'years': models.Member.YEARS}) def onboard_index(request): return render(request, 'ssmembership/onboard/index.html') def onboard_signed(request): if 'email' not in request.GET: return HttpResponse('Expected an email address', status=400) if 'sig' not in request.GET: return HttpResponse('Expected a signature parameter', status=400) sig_expected = hmac.new(settings.SECRET_KEY_MEMBERSIG.encode('utf-8'), request.GET['email'].encode('utf-8'), 'sha256').hexdigest() if not hmac.compare_digest(sig_expected, request.GET['sig']): return HttpResponse('Invalid signature', status=403) member = monboard.by_email(request.GET['email']) return render(request, 'ssmembership/onboard/review.html', { 'member': member, 'years': models.Member.YEARS, 'email_orig': member.email if member else None, 'sig': sig_expected }) @ratelimit(key=settings.RATELIMIT_KEY, rate='100/h') def onboard_search(request): if request.method != 'POST': return redirect(reverse('onboard_index')) if request.limited: return HttpResponse('Too many requests', status=429) member = monboard.by_email(request.POST['email']) if member and member.student_id != request.POST['student_id']: member = None return render(request, 'ssmembership/onboard/review.html', { 'member': member, 'years': models.Member.YEARS, 'email_orig': member.email if member else None, 'sig': hmac.new(settings.SECRET_KEY_MEMBERSIG.encode('utf-8'), member.email.encode('utf-8'), 'sha256').hexdigest() if member else None }) def onboard_save(request): if request.method != 'POST': return redirect(reverse('onboard_index')) sig_expected = hmac.new(settings.SECRET_KEY_MEMBERSIG.encode('utf-8'), request.POST['email_orig'].encode('utf-8'), 'sha256').hexdigest() if not hmac.compare_digest(sig_expected, request.POST['sig']): return HttpResponse('Invalid signature', status=403) member = monboard.by_email(request.POST['email_orig']) if not member: return render(request, 'ssmembership/onboard/review.html', { 'member': member }) member.student_id = request.POST['student_id'] member.email = request.POST['email'] member.first_name = request.POST['first_name'] member.last_name = request.POST['last_name'] member.phone = request.POST['phone'] member.year = int(request.POST['year']) member.is_msa = True if request.POST['is_msa'] == '1' else '0' errors = member.validation_problems() if models.Member.objects.filter(email=request.POST['email']).count() > 0: errors.append('Member with this email already exists') if len(errors) > 0: return render(request, 'ssmembership/onboard/review.html', { 'member': member, 'years': models.Member.YEARS, 'email_orig': request.POST['email_orig'], 'sig': request.POST['sig'], 'errors': errors }) with transaction.atomic(): member.save() # Update bulletin import sspromotions.models sspromotions.models.BulletinSubscription.set_member_subscribed(member, True if request.POST['bulletin_subscribe'] == '1' else False) for group in sspromotions.models.Group.objects.filter(subscribable=True).all(): if ('bulletin_group_' + str(group.id)) in request.POST and request.POST['bulletin_group_' + str(group.id)]: group.subscribe_member(member, True) else: group.subscribe_member(member, False) monboard.delete_by_email(request.POST['email_orig']) return render(request, 'ssmembership/onboard/complete.html') def signup_index(request): return render(request, 'ssmembership/signup/index.html', { 'member': models.Member(), 'years': models.Member.YEARS }) def signup_save(request): if request.method != 'POST': return redirect(reverse('signup_index')) member = models.Member() member.student_id = request.POST['student_id'] member.email = request.POST['email'] member.first_name = request.POST['first_name'] member.last_name = request.POST['last_name'] member.phone = request.POST['phone'] member.year = int(request.POST['year']) member.is_msa = True if request.POST['is_msa'] == '1' else '0' member.member_type = 2 # Associate Member # Calculate expiration date member.expires = timezone.localtime(timezone.now()).date().replace(month=3, day=20) member.expires = member.expires.replace(year=member.expires.year+1) if member.expires < timezone.localtime(timezone.now()).date(): # Add 1 year if after Mar 20, else add 2 years member.expires = member.expires.replace(year=member.expires.year+1) errors = member.validation_problems() if models.Member.objects.filter(email=request.POST['email']).count() > 0: errors.append('Member with this email already exists') if len(errors) > 0: return render(request, 'ssmembership/signup/index.html', { 'member': member, 'years': models.Member.YEARS, 'errors': errors }) with transaction.atomic(): member.save() # Update bulletin import sspromotions.models sspromotions.models.BulletinSubscription.set_member_subscribed(member, True if request.POST['bulletin_subscribe'] == '1' else False) for group in sspromotions.models.Group.objects.filter(subscribable=True).all(): if ('bulletin_group_' + str(group.id)) in request.POST and request.POST['bulletin_group_' + str(group.id)]: group.subscribe_member(member, True) else: group.subscribe_member(member, False) return render(request, 'ssmembership/signup/complete.html')