Skip to content

Commit

Permalink
Merge 2f72e99 into e23eb09
Browse files Browse the repository at this point in the history
  • Loading branch information
teleyinex committed Oct 3, 2017
2 parents e23eb09 + 2f72e99 commit 37f502d
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 5 deletions.
4 changes: 2 additions & 2 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@
#
# The short X.Y version.

version = 'v2.7.1'
version = 'v2.7.2'
# The full version, including alpha/beta/rc tags.
release = 'v2.7.1'
release = 'v2.7.2'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
3 changes: 3 additions & 0 deletions pybossa/forms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,3 +475,6 @@ class AvatarUploadForm(Form):
y1 = IntegerField(label=None, widget=HiddenInput(), default=0)
x2 = IntegerField(label=None, widget=HiddenInput(), default=0)
y2 = IntegerField(label=None, widget=HiddenInput(), default=0)

class TransferOwnershipForm(Form):
email_addr = EmailField(lazy_gettext('Email of the new owner'))
3 changes: 2 additions & 1 deletion pybossa/forms/projects_view_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@
BlogpostForm,
PasswordForm,
GenericBulkTaskImportForm,
AvatarUploadForm)
AvatarUploadForm,
TransferOwnershipForm)
2 changes: 1 addition & 1 deletion pybossa/themes/default
47 changes: 47 additions & 0 deletions pybossa/view/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1819,3 +1819,50 @@ def reset_secret_key(short_name):
msg = gettext('New secret key generated')
flash(msg, 'success')
return redirect_content_type(url_for('.update', short_name=short_name))

@blueprint.route('/<short_name>/transferownership', methods=['GET', 'POST'])
@login_required
def transfer_ownership(short_name):
"""Transfer project ownership."""

project, owner, ps = project_by_shortname(short_name)

pro = pro_features()

title = project_title(project, "Results")

ensure_authorized_to('update', project)

form = TransferOwnershipForm(request.body)

if request.method == 'POST' and form.validate():
new_owner = user_repo.filter_by(email_addr=form.email_addr.data)
if len(new_owner) == 1:
new_owner = new_owner[0]
project.owner_id = new_owner.id
project_repo.update(project)
msg = gettext("Project owner updated")
return redirect_content_type(url_for('.details',
short_name=short_name))
else:
msg = gettext("New project owner not found by email")
flash(msg, 'info')
return redirect_content_type(url_for('.transfer_ownership',
short_name=short_name))
else:
owner_serialized = cached_users.get_user_summary(owner.name)
project = add_custom_contrib_button_to(project, get_user_id_or_ip(), ps=ps)
response = dict(template='/projects/transferownership.html',
project=project,
owner=owner_serialized,
n_tasks=ps.n_tasks,
overall_progress=ps.overall_progress,
n_task_runs=ps.n_task_runs,
last_activity=ps.last_activity,
n_completed_tasks=ps.n_completed_tasks,
n_volunteers=ps.n_volunteers,
title=title,
pro_features=pro,
form=form,
target='.transfer_ownership')
return handle_content_type(response)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@

setup(
name = 'pybossa',
version = '2.7.1',
version = '2.7.2',
packages = find_packages(),
install_requires = requirements,
# only needed when installing directly from setup.py (PyPi, eggs?) and pointing to e.g. a git repo.
Expand Down
126 changes: 126 additions & 0 deletions test/test_view/test_project_transferownership.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# -*- coding: utf8 -*-
# This file is part of PYBOSSA.
#
# Copyright (C) 2017 Scifabric
#
# PYBOSSA 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.
#
# PYBOSSA 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 PYBOSSA. If not, see <http://www.gnu.org/licenses/>.
from default import db, with_context
from factories import ProjectFactory, UserFactory
from helper import web
from pybossa.repositories import UserRepository, ProjectRepository
import json

project_repo = ProjectRepository(db)
user_repo = UserRepository(db)

class TestProjectTransferOwnership(web.Helper):

@with_context
def test_transfer_anon_get(self):
"""Test transfer ownership page is not shown to anon."""
project = ProjectFactory.create()
url = '/project/%s/transferownership' % project.short_name
res = self.app_get_json(url, follow_redirects=True)
assert 'signin' in res.data, res.data

@with_context
def test_transfer_auth_not_owner_get(self):
"""Test transfer ownership page is forbidden for not owner."""
admin, owner, user = UserFactory.create_batch(3)
project = ProjectFactory.create(owner=owner)
url = '/project/%s/transferownership?api_key=%s' % (project.short_name,
user.api_key)
res = self.app_get_json(url, follow_redirects=True)
data = json.loads(res.data)
assert data['code'] == 403, data

@with_context
def test_transfer_auth_owner_get(self):
"""Test transfer ownership page is ok for owner."""
admin, owner, user = UserFactory.create_batch(3)
project = ProjectFactory.create(owner=owner)
url = '/project/%s/transferownership?api_key=%s' % (project.short_name,
owner.api_key)
res = self.app_get_json(url, follow_redirects=True)
data = json.loads(res.data)
assert data['form'], data
assert data['form']['errors'] == {}, data
assert data['form']['email_addr'] is None, data
assert data['form']['csrf'] is not None, data

@with_context
def test_transfer_auth_admin_get(self):
"""Test transfer ownership page is ok for admin."""
admin, owner, user = UserFactory.create_batch(3)
project = ProjectFactory.create(owner=owner)
url = '/project/%s/transferownership?api_key=%s' % (project.short_name,
admin.api_key)
res = self.app_get_json(url, follow_redirects=True)
data = json.loads(res.data)
assert data['form'], data
assert data['form']['errors'] == {}, data
assert data['form']['email_addr'] is None, data
assert data['form']['csrf'] is not None, data

@with_context
def test_transfer_auth_owner_post(self):
"""Test transfer ownership page post is ok for owner."""
admin, owner, user = UserFactory.create_batch(3)
project = ProjectFactory.create(owner=owner)
url = '/project/%s/transferownership?api_key=%s' % (project.short_name,
owner.api_key)

assert project.owner_id == owner.id
payload = dict(email_addr=user.email_addr)
res = self.app_post_json(url, data=payload,
follow_redirects=True)
data = json.loads(res.data)
assert data['next'] is not None, data

err_msg = "The project owner id should be different"
assert project.owner_id == user.id, err_msg


@with_context
def test_transfer_auth_admin_post(self):
"""Test transfer ownership page post is ok for admin."""
admin, owner, user = UserFactory.create_batch(3)
project = ProjectFactory.create(owner=owner)
url = '/project/%s/transferownership?api_key=%s' % (project.short_name,
admin.api_key)

assert project.owner_id == owner.id
payload = dict(email_addr=user.email_addr)
res = self.app_post_json(url, data=payload,
follow_redirects=True)
data = json.loads(res.data)
assert data['next'] is not None, data

err_msg = "The project owner id should be different"
assert project.owner_id == user.id, err_msg

@with_context
def test_transfer_auth_user_post(self):
"""Test transfer ownership page post is forbidden for not owner."""
admin, owner, user = UserFactory.create_batch(3)
project = ProjectFactory.create(owner=owner)
url = '/project/%s/transferownership?api_key=%s' % (project.short_name,
user.api_key)

assert project.owner_id == owner.id
payload = dict(email_addr=user.email_addr)
res = self.app_post_json(url, data=payload,
follow_redirects=True)
data = json.loads(res.data)
assert data['code'] == 403, data

0 comments on commit 37f502d

Please sign in to comment.