Skip to content

Commit 201d3ec

Browse files
anyone can duplicate public project (structure only)
1 parent e2fc21b commit 201d3ec

File tree

2 files changed

+94
-20
lines changed

2 files changed

+94
-20
lines changed

api/nodes/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,7 @@ def create(self, validated_data):
787787
template_node = Node.load(template_from)
788788
if template_node is None:
789789
raise exceptions.NotFound
790-
if not template_node.has_permission(user, osf_permissions.READ, check_parent=False):
790+
if not template_node.is_public and not template_node.is_contributor(user):
791791
raise exceptions.PermissionDenied
792792
validated_data.pop('creator')
793793
changed_data = {template_from: validated_data}

api_tests/nodes/views/test_node_list.py

Lines changed: 93 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,25 +1479,6 @@ def test_create_from_template_errors(self, app, user_one, user_two, url):
14791479
expect_errors=True)
14801480
assert res.status_code == 404
14811481

1482-
# test_403_on_create_from_template_of_unauthorized_project
1483-
template_from = ProjectFactory(creator=user_two, is_public=True)
1484-
templated_project_data = {
1485-
'data': {
1486-
'type': 'nodes',
1487-
'attributes':
1488-
{
1489-
'title': 'No permission',
1490-
'category': 'project',
1491-
'template_from': template_from._id,
1492-
}
1493-
}
1494-
}
1495-
res = app.post_json_api(
1496-
url, templated_project_data,
1497-
auth=user_one.auth,
1498-
expect_errors=True)
1499-
assert res.status_code == 403
1500-
15011482
def test_creates_project_from_template(self, app, user_one, category, url):
15021483
template_from = ProjectFactory(creator=user_one, is_public=True)
15031484
template_component = ProjectFactory(
@@ -1530,6 +1511,99 @@ def test_creates_project_from_template(self, app, user_one, category, url):
15301511
assert len(new_project.nodes) == len(template_from.nodes)
15311512
assert new_project.nodes[0].title == template_component.title
15321513

1514+
def test_non_contributor_create_project_from_public_template_success(self, app, user_one, category, url):
1515+
template_from = ProjectFactory(creator=user_one, is_public=True)
1516+
user_without_permissions = AuthUserFactory()
1517+
templated_project_data = {
1518+
'data': {
1519+
'type': 'nodes',
1520+
'attributes':
1521+
{
1522+
'title': 'template from project',
1523+
'category': category,
1524+
'template_from': template_from._id,
1525+
}
1526+
}
1527+
}
1528+
with capture_notifications():
1529+
res = app.post_json_api(
1530+
url, templated_project_data,
1531+
auth=user_without_permissions.auth
1532+
)
1533+
assert res.status_code == 201
1534+
1535+
def test_non_contributor_create_project_from_private_template_no_permission_fails(self, app, user_one, category, url):
1536+
template_from = ProjectFactory(creator=user_one, is_public=False)
1537+
user_without_permissions = AuthUserFactory()
1538+
templated_project_data = {
1539+
'data': {
1540+
'type': 'nodes',
1541+
'attributes':
1542+
{
1543+
'title': 'template from project',
1544+
'category': category,
1545+
'template_from': template_from._id,
1546+
}
1547+
}
1548+
}
1549+
res = app.post_json_api(
1550+
url, templated_project_data,
1551+
auth=user_without_permissions.auth,
1552+
expect_errors=True
1553+
)
1554+
assert res.status_code == 403
1555+
1556+
def test_contributor_create_project_from_private_template_with_permission_success(self, app, user_one, category, url):
1557+
template_from = ProjectFactory(creator=user_one, is_public=False)
1558+
user_without_permissions = AuthUserFactory()
1559+
template_from.add_contributor(user_without_permissions, permissions=permissions.READ, auth=Auth(user_one), save=True)
1560+
templated_project_data = {
1561+
'data': {
1562+
'type': 'nodes',
1563+
'attributes':
1564+
{
1565+
'title': 'template from project',
1566+
'category': category,
1567+
'template_from': template_from._id,
1568+
}
1569+
}
1570+
}
1571+
with capture_notifications():
1572+
res = app.post_json_api(
1573+
url, templated_project_data,
1574+
auth=user_without_permissions.auth
1575+
)
1576+
assert res.status_code == 201
1577+
assert template_from.has_permission(user_without_permissions, permissions.READ)
1578+
1579+
template_from.update_contributor(
1580+
user_without_permissions,
1581+
permission=permissions.WRITE,
1582+
auth=Auth(user_one),
1583+
save=True,
1584+
visible=True
1585+
)
1586+
res = app.post_json_api(
1587+
url, templated_project_data,
1588+
auth=user_without_permissions.auth
1589+
)
1590+
assert res.status_code == 201
1591+
assert template_from.has_permission(user_without_permissions, permissions.WRITE)
1592+
1593+
template_from.update_contributor(
1594+
user_without_permissions,
1595+
permission=permissions.ADMIN,
1596+
auth=Auth(user_one),
1597+
save=True,
1598+
visible=True
1599+
)
1600+
res = app.post_json_api(
1601+
url, templated_project_data,
1602+
auth=user_without_permissions.auth
1603+
)
1604+
assert res.status_code == 201
1605+
assert template_from.has_permission(user_without_permissions, permissions.ADMIN)
1606+
15331607
def test_creates_project_creates_project_and_sanitizes_html(
15341608
self, app, user_one, category, url):
15351609
title = '<em>Cool</em> <strong>Project</strong>'

0 commit comments

Comments
 (0)