from django.shortcuts import render from django.contrib.auth.decorators import permission_required from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import ensure_csrf_cookie from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseRedirect from django.core.mail import send_mail from django.conf import settings import json import requests import logging from members.models import Member, Request from members.forms import MemberForm '''Rest API''' from members.serializers import MemberSerializer, MemberRequestSerializer from rest_framework import generics from rest_framework import generics, status, authentication, exceptions, permissions from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from members.permissions import HasRights from members.throttles import BurstRateThrottle, SustainedRateThrottle # Logger function, you can use the same idea when implementing other loggers to other apps memberlogger = logging.getLogger(__name__) logging.basicConfig(format='[%(levelname)s]%(asctime)s %(message)s', level=settings.LOGGERLEVEL, filename=settings.LOGPATH) #API views ######################################## class MembersList(generics.ListCreateAPIView): queryset = Member.objects.all() serializer_class = MemberSerializer permission_classes = (HasRights, permissions.IsAuthenticated, ) throttle_classes = (BurstRateThrottle, SustainedRateThrottle, ) class MemberDetails(generics.RetrieveUpdateDestroyAPIView): queryset = Member.objects.all() serializer_class = MemberSerializer permission_classes = (HasRights, permissions.IsAuthenticated, ) throttle_classes = (BurstRateThrottle, SustainedRateThrottle, ) class MemberRequestList(generics.ListCreateAPIView): queryset = Request.objects.all() serializer_class = MemberRequestSerializer permission_classes = (HasRights, permissions.IsAuthenticated, ) throttle_classes = (BurstRateThrottle, SustainedRateThrottle, ) class MemberRequestDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Request.objects.all() serializer_class = MemberRequestSerializer permission_classes = (HasRights, permissions.IsAuthenticated, ) throttle_classes = (BurstRateThrottle, SustainedRateThrottle, ) ######################################## # function to validate reCaptcha def validate_recaptcha(response): values = { 'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY, 'response': response, } url = "https://www.google.com/recaptcha/api/siteverify" headers = {'Content-type': 'application/x-www-form-urlencoded'} resp = requests.post(url, values, headers=headers) result = json.loads(resp.text) memberlogger.info(result) if not result["success"]: return False return True def send_mail_wrapper(subject, message): send_mail( subject, message, 'no-reply@sahkoinsinoorikilta.fi', ['viestintamestari@sahkoinsinoorikilta.fi'], fail_silently=False ) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') def member_list(request, *args, **kwargs): context = {} return render(request, 'member_list.html', context) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') def add_member(request, *args, **kwargs): form = MemberForm() return render(request, 'add_member.html', {'form': form}) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') def add_many_members(request, *args, **kwargs): return render(request, 'add_many_members.html', {}) @ensure_csrf_cookie @require_http_methods(["POST"]) @permission_required('members.change_member', login_url='/login') def submit_member(request, *args, **kwargs): form = MemberForm(request.POST) if form.is_valid(): print(request.POST) return HttpResponse('jee') else: print(request.POST) print(form.errors) return HttpResponse('oh shit') return HttpResponseRedirect('/members') @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') def list_applications(request, *args, **kwargs): return render(request, 'list_applications.html', {}) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') def tommy_blooper(request, *args, **kwargs): return render(request, 'tommy_blooper.html', {}) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') def edit_member(request, *args, **kwargs): i = kwargs.pop('index', None); if i is None: return HttpResponse(status=500, error="{'error': 'No member id specified'}") else: return render(request, 'edit_member.html', {'member_id' : i}) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') def edit_application(request, *args, **kwargs): i = kwargs.pop('index', None); if i is None: return HttpResponse(status=500, error="{'error': 'No member id specified'}") else: return render(request, 'edit_application.html', {'member_id' : i}) @ensure_csrf_cookie def application_index(request, *args, **kwargs): return render(request, 'application_index.html', {}) @ensure_csrf_cookie def application_success_index(request, *args, **kwargs): return render(request, 'application_success.html', {}) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') def members(request, *args, **kwargs): mems = list(map(lambda m: m.get_dict(), Member.objects.all())) return HttpResponse(json.dumps(mems)) @ensure_csrf_cookie @require_http_methods(["GET", "POST", "DELETE", "PUT"]) @permission_required('members.change_member', login_url='/login') def member(request, *args, **kwargs): # get, put and delete together since all operate on existing objects if request.method in ['GET', 'PUT', 'DELETE']: # get object by id or give 404 idx = kwargs.pop("idx", None) try: mem = Member.objects.get(pk=idx) except Member.DoesNotExist: resp = HttpResponse('{"error":"object not found"}') resp.status_code = 404 return resp # delete object if requested if request.method == 'DELETE': try: mem.delete() return HttpResponse('{"status":"success"}') except: resp = HttpResponse('{"error" : "could not delete object"}') resp.status_code = 500 return resp @ensure_csrf_cookie @require_http_methods(["POST"]) @permission_required('members.change_member', login_url='/login') def csv_import(request, *args, **kwargs): data = request.body.decode("utf-8") try: payload = json.loads(data) except: return HttpResponse(json.dumps({'error': 'Malformed request'}), 400) resp_data = Member.import_csv(payload['csv']) resp = HttpResponse(json.dumps(resp_data)) if resp_data['status'] == 'failure': resp.status_code = 400 memberlogger.warning('POST request failed with status code {}'.format(resp.status_code)) return resp @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') def member_requests(request, *args, **kwargs): reqs = list(map(lambda r: r.get_dict(), MemberRequest.objects.all())) return HttpResponse(json.dumps(reqs)) @ensure_csrf_cookie def new_member_request(request, *args, **kwargs): try: data = json.loads(request.body.decode("utf-8")) # get captcha response from member captcha = data.pop("reCaptchaResponse", "") # send response to google and check it out captcha_ok = validate_recaptcha(captcha) # if not ok, inform user if not captcha_ok: return HttpResponseBadRequest('{"error": "Captcha not ok. Please try again."}') # if ok continue mem = Member.create_from_dict(data) req = MemberRequest.objects.create(member=mem) # Build the email body subject = 'New application' message = 'You have new application\r\n' message += 'Member info:\r\n' message += 'First name: ' + mem.first_name + '\r\n' message += 'Last name: ' + mem.last_name + '\r\n' message += 'Email: ' + mem.email + '\r\n' message += 'Place of residence: ' + mem.POR + '\r\n' message += 'AYY-membership: ' + str(mem.AYY) + '\r\n' message += 'To mail list: ' + str(mem.jas) + '\r\n' message += 'Created: ' + mem.created.isoformat(' ') + '\r\n' message += 'Please go to the https://sika.sahkoinsinoorikilta.fi/members/ and do something about it!\r\n' # TODO: send mail when application is ready # send_mail_wrapper(subject, message) return HttpResponse(json.dumps(mem.get_dict())) except ValueError: return HttpResponseBadRequest('{"error" : "Invalid parameters supplied"}') except TimeoutError: return HttpResponseBadRequest('{"error" : "Much error, no connection"}') @ensure_csrf_cookie @require_http_methods(["GET", "POST", "DELETE"]) @permission_required('members.change_member', login_url='/login') def handle_mem_request(request, idx, *args, **kwargs): try: req = MemberRequest.objects.get(pk=idx) except MemberRequest.DoesNotExist: resp = HttpResponse('{"error":"object not found"}') resp.status_code = 404 return resp if request.method == 'GET': return HttpResponse(json.dumps(req.get_dict())) elif request.method == 'DELETE': req.member.delete() else: # method == POST because other aren't allowed here req.delete() return HttpResponse('{"status":"success"}') @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') def export_csv(request, *args, **kwargs): import csv response = HttpResponse() response['Content-type'] = 'text/csv' response['Accept'] = 'text/csv' response['Content-Disposition'] = 'filename; filename=members.csv' writer = csv.writer(response, csv.excel) response.write(u'\ufeff'.encode('utf8')) # BOM (optional...Excel needs it to open UTF-8 file properly) for obj in Member.objects.all(): data = obj.get_dict() field_list = map(lambda s: str(data[s]), ['id', 'first_name', 'last_name', 'email', 'POR', 'AYY', 'jas', 'created', 'paid']) writer.writerow(field_list) return response