forked from GithubBackups/healthchecks
Check membership when initiating project's transfer. Use transaction.atomic() when completing the transfer.
This commit is contained in:
parent
57da17b8e2
commit
ca715dd8d4
@ -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="alice@example.org", password="password")
|
||||||
|
|
||||||
|
form = {"transfer_project": "1", "email": "charlie@example.org"}
|
||||||
|
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()
|
||||||
|
@ -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)
|
membership.transfer_request_date = now()
|
||||||
q.update(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,13 +377,13 @@ def project(request, code):
|
|||||||
if not tr.can_accept():
|
if not tr.can_accept():
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
|
|
||||||
# 1. Remove user's membership
|
with transaction.atomic():
|
||||||
tr.delete()
|
# 1. Reuse the existing membership, and change its user
|
||||||
|
tr.user = project.owner
|
||||||
|
tr.transfer_request_date = None
|
||||||
|
tr.save()
|
||||||
|
|
||||||
# 2. Invite the current owner as a member
|
# 2. Change project's owner
|
||||||
Member.objects.create(user=project.owner, project=project)
|
|
||||||
|
|
||||||
# 3. Change project's owner
|
|
||||||
project.owner = request.user
|
project.owner = request.user
|
||||||
project.save()
|
project.save()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user