Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 33bc69e

Browse files
authored
Merge pull request #7210 from ckan/change-user-creation-defaults-2.9
Change user creation defaults [2.9]
2 parents 7126c4c + af1a2fd commit 33bc69e

13 files changed

Lines changed: 114 additions & 13 deletions

File tree

ckan/authz.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ def user_is_collaborator_on_dataset(user_id, dataset_id, capacity=None):
478478
'user_delete_groups': True,
479479
'user_delete_organizations': True,
480480
'create_user_via_api': False,
481-
'create_user_via_web': True,
481+
'create_user_via_web': False,
482482
'roles_that_cascade_to_sub_groups': 'admin',
483483
'public_activity_stream_detail': False,
484484
'allow_dataset_collaborators': False,

ckan/config/deployment.ini_tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ ckan.auth.user_create_organizations = false
7676
ckan.auth.user_delete_groups = true
7777
ckan.auth.user_delete_organizations = true
7878
ckan.auth.create_user_via_api = false
79-
ckan.auth.create_user_via_web = true
79+
ckan.auth.create_user_via_web = false
8080
ckan.auth.roles_that_cascade_to_sub_groups = admin
8181
ckan.auth.public_user_details = true
8282
ckan.auth.public_activity_stream_detail = true

ckan/lib/uploader.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,18 @@ def verify_type(self):
204204
return
205205

206206
mimetypes = aslist(
207-
config.get("ckan.upload.{}.mimetypes".format(self.object_type)))
207+
config.get(
208+
"ckan.upload.{}.mimetypes".format(self.object_type),
209+
["image/png", "image/gif", "image/jpeg"]
210+
)
211+
)
208212

209213
types = aslist(
210-
config.get("ckan.upload.{}.types".format(self.object_type)))
214+
config.get(
215+
"ckan.upload.{}.types".format(self.object_type),
216+
["image"]
217+
)
218+
)
211219

212220
if not mimetypes and not types:
213221
return

ckan/logic/action/create.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,8 @@ def user_invite(context, data_dict):
11561156
data['name'] = name
11571157
data['password'] = password
11581158
data['state'] = ckan.model.State.PENDING
1159-
user_dict = _get_action('user_create')(context, data)
1159+
create_context = dict(context, ignore_auth=True)
1160+
user_dict = _get_action('user_create')(create_context, data)
11601161
user = ckan.model.User.get(user_dict['id'])
11611162
member_dict = {
11621163
'username': user.id,

ckan/tests/controllers/test_user.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ def _get_user_edit_page(app):
2626

2727
@pytest.mark.usefixtures("clean_db", "with_request_context")
2828
class TestUser(object):
29+
30+
@pytest.mark.ckan_config("ckan.auth.create_user_via_web", True)
2931
def test_register_a_user(self, app):
3032
url = url_for("user.register")
3133
response = app.post(url=url, data={
@@ -44,6 +46,7 @@ def test_register_a_user(self, app):
4446
assert user["fullname"] == "New User"
4547
assert not (user["sysadmin"])
4648

49+
@pytest.mark.ckan_config("ckan.auth.create_user_via_web", True)
4750
def test_register_user_bad_password(self, app):
4851
response = app.post(url_for("user.register"), data={
4952
"save": "",

ckan/tests/legacy/functional/api/test_user.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ class TestUserActions(object):
175175
def initial_data(self, clean_db):
176176
CreateTestData.create()
177177

178+
@pytest.mark.ckan_config("ckan.auth.create_user_via_web", True)
178179
def test_user_create_simple(self):
179180
"""Simple creation of a new user by a non-sysadmin user."""
180181
context = {"model": model, "session": model.Session, "user": "tester"}

ckan/tests/lib/test_uploader.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,18 @@ def test_group_upload(self, monkeypatch, tmpdir, make_app, ckan_config):
7171
"""
7272
monkeypatch.setitem(ckan_config, u'ckan.storage_path', str(tmpdir))
7373
monkeypatch.setattr(ckan.lib.uploader, u'_storage_path', str(tmpdir))
74+
some_png = """
75+
89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
76+
00 00 00 01 00 00 00 01 08 02 00 00 00 90 77 53
77+
DE 00 00 00 0C 49 44 41 54 08 D7 63 F8 CF C0 00
78+
00 03 01 01 00 18 DD 8D B0 00 00 00 00 49 45 4E
79+
44 AE 42 60 82"""
80+
some_png = some_png.replace(u' ', u'').replace(u'\n', u'')
81+
some_png_bytes = bytes(bytearray.fromhex(some_png))
82+
7483
group = {u'clear_upload': u'',
7584
u'upload': FileStorage(
76-
six.BytesIO(six.ensure_binary(u'hello')),
85+
six.BytesIO(some_png_bytes),
7786
filename=u'logo.png',
7887
content_type=u'PNG'
7988
),
@@ -87,4 +96,8 @@ def test_group_upload(self, monkeypatch, tmpdir, make_app, ckan_config):
8796
app = make_app()
8897
resp = app.get(u'/uploads/group/' + group[u'url'])
8998
assert resp.status_code == 200
90-
assert resp.body == u'hello'
99+
# PNG signature
100+
if six.PY3:
101+
assert resp.data.hex()[:16].upper() == u'89504E470D0A1A0A'
102+
else:
103+
assert resp.data.encode(u"hex")[:16].upper() == u'89504E470D0A1A0A'

ckan/tests/logic/action/test_create.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,7 @@ def test_create_organization_custom_type(self):
10681068

10691069

10701070
@pytest.mark.usefixtures("clean_db", "with_request_context")
1071+
@pytest.mark.ckan_config("ckan.auth.create_user_via_web", True)
10711072
class TestUserCreate(object):
10721073
def test_user_create_with_password_hash(self):
10731074
sysadmin = factories.Sysadmin()
@@ -1381,6 +1382,7 @@ def test_create_user_not_found(self):
13811382

13821383

13831384
@pytest.mark.usefixtures("clean_db")
1385+
@pytest.mark.ckan_config("ckan.auth.create_user_via_web", True)
13841386
class TestUserPluginExtras(object):
13851387

13861388
def test_stored_on_create_if_sysadmin(self):
@@ -1479,7 +1481,7 @@ def test_external_picture(self):
14791481
user_dict["image_display_url"] == "https://example.com/mypic.png"
14801482
)
14811483

1482-
def test_upload_non_picture_works_without_extra_config(
1484+
def test_upload_non_picture_not_works_without_extra_config(
14831485
self, create_with_upload):
14841486
params = {
14851487
"name": "test_user_1",
@@ -1488,7 +1490,35 @@ def test_upload_non_picture_works_without_extra_config(
14881490
"action": "user_create",
14891491
"upload_field_name": "image_upload",
14901492
}
1491-
assert create_with_upload("hello world", "file.txt", **params)
1493+
with pytest.raises(
1494+
logic.ValidationError, match="Unsupported upload type"):
1495+
assert create_with_upload("hello world", "file.txt", **params)
1496+
1497+
def test_upload_svg_fails_without_extra_config(
1498+
self, create_with_upload):
1499+
params = {
1500+
"name": "test_user_1",
1501+
"email": "[email protected]",
1502+
"password": "12345678",
1503+
"action": "user_create",
1504+
"upload_field_name": "image_upload",
1505+
}
1506+
with pytest.raises(
1507+
logic.ValidationError, match="Unsupported upload type"):
1508+
create_with_upload('<svg xmlns="http://www.w3.org/2000/svg"></svg>', "file.svg", **params)
1509+
1510+
def test_upload_svg_wrong_extension_fails_without_extra_config(
1511+
self, create_with_upload):
1512+
params = {
1513+
"name": "test_user_1",
1514+
"email": "[email protected]",
1515+
"password": "12345678",
1516+
"action": "user_create",
1517+
"upload_field_name": "image_upload",
1518+
}
1519+
with pytest.raises(
1520+
logic.ValidationError, match="Unsupported upload type"):
1521+
create_with_upload('<svg xmlns="http://www.w3.org/2000/svg"></svg>', "file.png", **params)
14921522

14931523
@pytest.mark.ckan_config("ckan.upload.user.types", "image")
14941524
def test_upload_non_picture(self, create_with_upload):
@@ -1517,7 +1547,6 @@ def test_upload_non_picture_with_png_extension(
15171547
logic.ValidationError, match="Unsupported upload type"):
15181548
create_with_upload("hello world", "file.png", **params)
15191549

1520-
@pytest.mark.ckan_config("ckan.upload.user.types", "image")
15211550
def test_upload_picture(self, create_with_upload):
15221551
params = {
15231552
"name": "test_user_1",

ckan/tests/logic/auth/test_create.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,3 +509,32 @@ def test_create_unowned_datasets(self):
509509
context = self._get_context(user)
510510
assert helpers.call_auth(
511511
'package_collaborator_create', context=context, id=dataset['id'])
512+
513+
514+
@pytest.mark.usefixtures("clean_db")
515+
class TestUserCreate:
516+
def test_sysadmin_can_create_via_api(self):
517+
sysadmin = factories.Sysadmin()
518+
context = {"user": sysadmin["name"], "model": core_model, "api_version": 3}
519+
assert helpers.call_auth("user_create", context)
520+
521+
def test_anon_can_not_create_via_web(self):
522+
context = {"user": None, "model": core_model}
523+
with pytest.raises(logic.NotAuthorized):
524+
helpers.call_auth("user_create", context)
525+
526+
def test_anon_cannot_create_via_api(self):
527+
context = {"user": None, "model": core_model, "api_version": 3}
528+
with pytest.raises(logic.NotAuthorized):
529+
helpers.call_auth("user_create", context)
530+
531+
@pytest.mark.ckan_config("ckan.auth.create_user_via_web", False)
532+
def test_anon_cannot_create_via_forbidden_web(self):
533+
context = {"user": None, "model": core_model}
534+
with pytest.raises(logic.NotAuthorized):
535+
helpers.call_auth("user_create", context)
536+
537+
@pytest.mark.ckan_config("ckan.auth.create_user_via_api", True)
538+
def test_anon_not_create_via_allowed_api(self):
539+
context = {"user": None, "model": core_model, "api_version": 3}
540+
assert helpers.call_auth("user_create", context)

ckan/tests/pytest_ckan/test_fixtures.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os
44

55
import pytest
6+
import six
67
from six.moves.urllib.parse import urlparse
78

89
import ckan.plugins as plugins
@@ -80,8 +81,17 @@ def test_create_organization(self, create_with_upload, ckan_config):
8081
context = {
8182
u"user": user["name"]
8283
}
84+
some_png = """
85+
89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
86+
00 00 00 01 00 00 00 01 08 02 00 00 00 90 77 53
87+
DE 00 00 00 0C 49 44 41 54 08 D7 63 F8 CF C0 00
88+
00 03 01 01 00 18 DD 8D B0 00 00 00 00 49 45 4E
89+
44 AE 42 60 82"""
90+
some_png = some_png.replace(u' ', u'').replace(u'\n', u'')
91+
some_png_bytes = bytes(bytearray.fromhex(some_png))
92+
8393
org = create_with_upload(
84-
b"\0\0\0", u"image.png",
94+
some_png_bytes, u"image.png",
8595
context=context,
8696
action=u"organization_create",
8797
upload_field_name=u"image_upload",
@@ -96,7 +106,11 @@ def test_create_organization(self, create_with_upload, ckan_config):
96106
assert os.path.isfile(image_path)
97107
with open(image_path, u"rb") as image:
98108
content = image.read()
99-
assert content == b"\0\0\0"
109+
# PNG signature
110+
if six.PY3:
111+
assert content.hex()[:16].upper() == u'89504E470D0A1A0A'
112+
else:
113+
assert content.encode(u"hex")[:16].upper() == u'89504E470D0A1A0A'
100114

101115
def test_create_resource(self, create_with_upload):
102116
dataset = factories.Dataset()

0 commit comments

Comments
 (0)