Browse Source

Check membership when initiating project's transfer. Use transaction.atomic() when completing the transfer.

pull/360/head
Pēteris Caune 5 years ago
parent
commit
ca715dd8d4
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
2 changed files with 27 additions and 13 deletions
  1. +7
    -0
      hc/accounts/tests/test_transfer_project.py
  2. +20
    -13
      hc/accounts/views.py

+ 7
- 0
hc/accounts/tests/test_transfer_project.py View File

@ -34,6 +34,13 @@ class ProjectTestCase(BaseTestCase):
r = self.client.post(self.url, form) r = self.client.post(self.url, form)
self.assertEqual(r.status_code, 403) self.assertEqual(r.status_code, 403)
def test_transfer_project_checks_membership(self):
self.client.login(username="[email protected]", password="password")
form = {"transfer_project": "1", "email": "[email protected]"}
r = self.client.post(self.url, form)
self.assertEqual(r.status_code, 400)
def test_cancel_works(self): def test_cancel_works(self):
self.bobs_membership.transfer_request_date = now() self.bobs_membership.transfer_request_date = now()
self.bobs_membership.save() self.bobs_membership.save()


+ 20
- 13
hc/accounts/views.py View File

@ -2,6 +2,7 @@ from datetime import timedelta as td
from urllib.parse import urlparse from urllib.parse import urlparse
import uuid import uuid
from django.db import transaction
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import login as auth_login from django.contrib.auth import login as auth_login
@ -339,21 +340,27 @@ def project(request, code):
form = forms.TransferForm(request.POST) form = forms.TransferForm(request.POST)
if form.is_valid(): if form.is_valid():
# Look up the proposed new owner
email = form.cleaned_data["email"] email = form.cleaned_data["email"]
try:
membership = project.member_set.filter(user__email=email).get()
except Member.DoesNotExist:
return HttpResponseBadRequest()
# Revoke any previous transfer requests # Revoke any previous transfer requests
project.member_set.update(transfer_request_date=None) project.member_set.update(transfer_request_date=None)
# Initiate the new request # Initiate the new request
q = project.member_set.filter(user__email=email)
q.update(transfer_request_date=now())
membership.transfer_request_date = now()
membership.save()
# Send an email notification
profile = Profile.objects.for_user(membership.user)
profile.send_transfer_request(project)
ctx["transfer_initiated"] = True ctx["transfer_initiated"] = True
ctx["transfer_status"] = "success" ctx["transfer_status"] = "success"
profile = Profile.objects.get(user__email=email)
profile.send_transfer_request(project)
elif "cancel_transfer" in request.POST: elif "cancel_transfer" in request.POST:
if not is_owner: if not is_owner:
return HttpResponseForbidden() return HttpResponseForbidden()
@ -370,15 +377,15 @@ def project(request, code):
if not tr.can_accept(): if not tr.can_accept():
return HttpResponseBadRequest() return HttpResponseBadRequest()
# 1. Remove user's membership
tr.delete()
# 2. Invite the current owner as a member
Member.objects.create(user=project.owner, project=project)
with transaction.atomic():
# 1. Reuse the existing membership, and change its user
tr.user = project.owner
tr.transfer_request_date = None
tr.save()
# 3. Change project's owner
project.owner = request.user
project.save()
# 2. Change project's owner
project.owner = request.user
project.save()
ctx["is_owner"] = True ctx["is_owner"] = True
messages.success(request, "You are now the owner of this project!") messages.success(request, "You are now the owner of this project!")


Loading…
Cancel
Save