Skip to content

Commit

Permalink
Merge pull request #627 from okfn/627-create-private-datasets
Browse files Browse the repository at this point in the history
You can not create a dataset private by default
  • Loading branch information
johnglover committed Mar 13, 2013
2 parents b5546f7 + 154eb25 commit 6a5d5c4
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 98 deletions.
1 change: 1 addition & 0 deletions ckan/logic/schema.py
Expand Up @@ -130,6 +130,7 @@ def default_package_schema():
'state': [ignore_not_package_admin, ignore_missing],
'type': [ignore_missing, unicode],
'owner_org': [owner_org_validator, unicode],
'private': [ignore_missing, boolean_validator],
'__extras': [ignore],
'__junk': [empty],
'resources': default_resource_schema(),
Expand Down
196 changes: 98 additions & 98 deletions ckan/tests/lib/test_dictization_schema.py
@@ -1,25 +1,16 @@
from nose.tools import assert_equal
from pprint import pprint, pformat
from difflib import unified_diff

from ckan.lib.create_test_data import CreateTestData
from ckan import model
from ckan.lib.dictization import (table_dictize,
table_dict_save)

from ckan.lib.dictization.model_dictize import (package_dictize,
group_dictize
)

from ckan.lib.dictization.model_save import package_dict_save

from ckan.logic.schema import default_package_schema, default_group_schema, \
default_tags_schema

group_dictize)
from ckan.logic.schema import (default_package_schema,
default_group_schema,
default_tags_schema)
from ckan.lib.navl.dictization_functions import validate

class TestBasicDictize:

class TestBasicDictize:
def setup(self):
self.context = {'model': model,
'session': model.Session}
Expand All @@ -35,7 +26,7 @@ def teardown_class(cls):

def remove_changable_columns(self, dict):
for key, value in dict.items():
if key.endswith('id') and key <> 'license_id':
if key.endswith('id') and key != 'license_id':
dict.pop(key)
if key == 'created':
dict.pop(key)
Expand All @@ -55,57 +46,58 @@ def remove_revision_id(self, dict):
return dict

def test_1_package_schema(self):

pkg = model.Session.query(model.Package).filter_by(name='annakarenina').first()
pkg = model.Session.query(model.Package)\
.filter_by(name='annakarenina')\
.first()

package_id = pkg.id

result = package_dictize(pkg, self.context)

self.remove_changable_columns(result)

result['name'] = 'anna2'
# we need to remove these as they have been added
del result['relationships_as_object']
del result['relationships_as_subject']

converted_data, errors = validate(result, default_package_schema(), self.context)


assert converted_data == {'extras': [{'key': u'genre', 'value': u'romantic novel'},
{'key': u'original media', 'value': u'book'}],
'groups': [{u'name': u'david',
u'title': u"Dave's books"},
{u'name': u'roger',
u'title': u"Roger's books",
}],
'license_id': u'other-open',
'name': u'anna2',
'type': u'dataset',
'notes': u'Some test notes\n\n### A 3rd level heading\n\n**Some bolded text.**\n\n*Some italicized text.*\n\nForeign characters:\nu with umlaut \xfc\n66-style quote \u201c\nforeign word: th\xfcmb\n\nNeeds escaping:\nleft arrow <\n\n<http://ckan.net/>\n\n',
'resources': [{'alt_url': u'alt123',
'description': u'Full text. Needs escaping: " Umlaut: \xfc',
'format': u'plain text',
'hash': u'abc123',
'size_extra': u'123',
'tracking_summary': {'recent': 0, 'total': 0},
'url': u'http://www.annakarenina.com/download/x=1&y=2'},
{'alt_url': u'alt345',
'description': u'Index of the novel',
'format': u'JSON',
'hash': u'def456',
'size_extra': u'345',
'tracking_summary': {'recent': 0, 'total': 0},
'url': u'http://www.annakarenina.com/index.json'}],
'tags': [{'name': u'Flexible \u30a1'},
{'name': u'russian'},
{'name': u'tolstoy'}],
'title': u'A Novel By Tolstoy',
'url': u'http://www.annakarenina.com',
'version': u'0.7a'}, pformat(converted_data)


converted_data, errors = validate(result,
default_package_schema(),
self.context)

expected_data = {
'extras': [{'key': u'genre', 'value': u'romantic novel'},
{'key': u'original media', 'value': u'book'}],
'groups': [{u'name': u'david',
u'title': u"Dave's books"},
{u'name': u'roger',
u'title': u"Roger's books"}],
'license_id': u'other-open',
'name': u'anna2',
'type': u'dataset',
'notes': u'Some test notes\n\n### A 3rd level heading\n\n**Some bolded text.**\n\n*Some italicized text.*\n\nForeign characters:\nu with umlaut \xfc\n66-style quote \u201c\nforeign word: th\xfcmb\n\nNeeds escaping:\nleft arrow <\n\n<http://ckan.net/>\n\n',
'private': False,
'resources': [{'alt_url': u'alt123',
'description': u'Full text. Needs escaping: " Umlaut: \xfc',
'format': u'plain text',
'hash': u'abc123',
'size_extra': u'123',
'tracking_summary': {'recent': 0, 'total': 0},
'url': u'http://www.annakarenina.com/download/x=1&y=2'},
{'alt_url': u'alt345',
'description': u'Index of the novel',
'format': u'JSON',
'hash': u'def456',
'size_extra': u'345',
'tracking_summary': {'recent': 0, 'total': 0},
'url': u'http://www.annakarenina.com/index.json'}],
'tags': [{'name': u'Flexible \u30a1'},
{'name': u'russian'},
{'name': u'tolstoy'}],
'title': u'A Novel By Tolstoy',
'url': u'http://www.annakarenina.com',
'version': u'0.7a'
}

assert converted_data == expected_data, pformat(converted_data)
assert not errors, errors

data = converted_data
Expand All @@ -114,34 +106,38 @@ def test_1_package_schema(self):
data["resources"][0]["url"] = 'fsdfafasfsaf'
data["resources"][1].pop("url")

converted_data, errors = validate(data, default_package_schema(), self.context)
converted_data, errors = validate(data,
default_package_schema(),
self.context)

assert errors == {
'name': [u'That URL is already in use.'],
'resources': [{}, {'url': [u'Missing value']}]
#'resources': [{}
# {'name': [u'That URL is already in use.']}]
}, pformat(errors)

data["id"] = package_id

converted_data, errors = validate(data, default_package_schema(), self.context)
converted_data, errors = validate(data,
default_package_schema(),
self.context)

assert errors == {
'resources': [{}, {'url': [u'Missing value']}]
}, pformat(errors)

data['name'] = '????jfaiofjioafjij'
converted_data, errors = validate(data, default_package_schema(), self.context)

converted_data, errors = validate(data,
default_package_schema(),
self.context)
assert errors == {
'name': [u'Url must be purely lowercase alphanumeric (ascii) characters and these symbols: -_'],
'name': [u'Url must be purely lowercase alphanumeric (ascii) '
'characters and these symbols: -_'],
'resources': [{}, {'url': [u'Missing value']}]
},pformat(errors)
}, pformat(errors)

def test_2_group_schema(self):

group = model.Session.query(model.Group).first()

data = group_dictize(group, self.context)

# we don't want these here
Expand All @@ -150,40 +146,47 @@ def test_2_group_schema(self):
del data['tags']
del data['extras']

converted_data, errors = validate(data, default_group_schema(), self.context)
group_pack = sorted(group.packages(), key=lambda x:x.id)

converted_data["packages"] = sorted(converted_data["packages"], key=lambda x:x["id"])

expected = {'description': u'These are books that David likes.',
'id': group.id,
'name': u'david',
'is_organization': False,
'type': u'group',
'image_url': u'',
'packages': sorted([{'id': group_pack[0].id,
'name': group_pack[0].name,
'title': group_pack[0].title},
{'id': group_pack[1].id,
'name': group_pack[1].name,
'title':group_pack[1].title}],
key=lambda x:x["id"]),
'title': u"Dave's books",
'approval_status': u'approved'}

converted_data, errors = validate(data,
default_group_schema(),
self.context)
group_pack = sorted(group.packages(), key=lambda x: x.id)

converted_data["packages"] = sorted(converted_data["packages"],
key=lambda x: x["id"])

expected = {
'description': u'These are books that David likes.',
'id': group.id,
'name': u'david',
'is_organization': False,
'type': u'group',
'image_url': u'',
'packages': sorted([{'id': group_pack[0].id,
'name': group_pack[0].name,
'title': group_pack[0].title},
{'id': group_pack[1].id,
'name': group_pack[1].name,
'title':group_pack[1].title}],
key=lambda x: x["id"]),
'title': u"Dave's books",
'approval_status': u'approved'
}

assert not errors
assert converted_data == expected, pformat(converted_data) + '\n\n' + pformat(expected)

assert converted_data == expected, pformat(converted_data)


data["packages"].sort(key=lambda x:x["id"])
data["packages"].sort(key=lambda x: x["id"])
data["packages"][0]["id"] = 'fjdlksajfalsf'
data["packages"][1].pop("id")
data["packages"][1].pop("name")

converted_data, errors = validate(data, default_group_schema(), self.context)
assert errors == {'packages': [{'id': [u'Not found: Dataset']}, {'id': [u'Missing value']}]} , pformat(errors)
converted_data, errors = validate(data,
default_group_schema(),
self.context)
assert errors == {
'packages': [{'id': [u'Not found: Dataset']},
{'id': [u'Missing value']}]
}, pformat(errors)

def test_3_tag_schema_allows_spaces(self):
"""Asserts that a tag name with space is valid"""
Expand All @@ -192,8 +195,7 @@ def test_3_tag_schema_allows_spaces(self):
'name': u'with space',
'revision_timestamp': ignored,
'state': ignored
}

}
_, errors = validate(data, default_tags_schema(), self.context)
assert not errors, str(errors)

Expand All @@ -204,8 +206,7 @@ def test_4_tag_schema_allows_limited_punctuation(self):
'name': u'.-_',
'revision_timestamp': ignored,
'state': ignored
}

}
_, errors = validate(data, default_tags_schema(), self.context)
assert not errors, str(errors)

Expand All @@ -216,14 +217,13 @@ def test_5_tag_schema_allows_capital_letters(self):
'name': u'CAPITALS',
'revision_timestamp': ignored,
'state': ignored
}

}
_, errors = validate(data, default_tags_schema(), self.context)
assert not errors, str(errors)

def test_6_tag_schema_disallows_most_punctuation(self):
"""Asserts most punctuation is disallowed"""
not_allowed=r'!?"\'+=:;@#~[]{}()*&^%$,'
not_allowed = r'!?"\'+=:;@#~[]{}()*&^%$,'
ignored = ""
data = {
'revision_timestamp': ignored,
Expand Down
54 changes: 54 additions & 0 deletions ckan/tests/logic/test_action.py
Expand Up @@ -179,6 +179,60 @@ def test_03_create_update_package(self):
package_created.pop('metadata_modified')
assert package_updated == package_created#, (pformat(json.loads(res.body)), pformat(package_created['result']))

def test_03_create_private_package(self):

def _do_request(package_dict):
postparams = '%s=1' % json.dumps(package_dict)
res = self.app.post('/api/action/package_create', params=postparams,
extra_environ={'Authorization': str(self.sysadmin_user.apikey)})
package_created = json.loads(res.body)['result']
return package_created

# Create a dataset without specifying visibility
package_dict = {
'extras': [{'key': u'original media','value': u'"book"'}],
'license_id': u'other-open',
'maintainer_email': None,
'name': u'annakarenina_vis',
'notes': u'Some test now',
'resources': [{'alt_url': u'alt123',
'description': u'Full text.',
'extras': {u'alt_url': u'alt123', u'size': u'123'},
'format': u'plain text',
'hash': u'abc123',
'position': 0,
'url': u'http://www.annakarenina.com/download/'},
{'alt_url': u'alt345',
'description': u'Index of the novel',
'extras': {u'alt_url': u'alt345', u'size': u'345'},
'format': u'JSON',
'hash': u'def456',
'position': 1,
'url': u'http://www.annakarenina.com/index.json'}],
'tags': [{'name': u'russian'}, {'name': u'tolstoy'}],
'title': u'A Novel By Tolstoy',
'url': u'http://www.annakarenina.com',
'version': u'0.7a',
}

package_created = _do_request(package_dict)
assert package_created['private'] is False

# Create a new one, explicitly saying it is public
package_dict['name'] = u'annakareninanew_vis_public'
package_dict['private'] = False

package_created_public = _do_request(package_dict)
assert package_created_public['private'] is False

# Create a new one, explicitly saying it is private
package_dict['name'] = u'annakareninanew_vis_private'
package_dict['private'] = True

package_created_private = _do_request(package_dict)
assert package_created_private['private'] is True


def test_18_create_package_not_authorized(self):
# I cannot understand the logic on this one we seem to be user
# tester but no idea how.
Expand Down

0 comments on commit 6a5d5c4

Please sign in to comment.