diff --git a/ckan/lib/app_globals.py b/ckan/lib/app_globals.py index 64bed2e1c80..f93a11e73f5 100644 --- a/ckan/lib/app_globals.py +++ b/ckan/lib/app_globals.py @@ -172,10 +172,6 @@ def _check_uptodate(self): self._mutex.release() def _init(self): - self.favicon = config.get('ckan.favicon', '/images/icons/ckan.ico') - facets = config.get('search.facets', 'groups tags res_format license capacity') - self.facets = facets.split() - # process the config_details to set globals for name, options in config_details.items(): if 'name' in options: diff --git a/ckan/lib/dictization/model_dictize.py b/ckan/lib/dictization/model_dictize.py index 247822c1cf6..431408ca788 100644 --- a/ckan/lib/dictization/model_dictize.py +++ b/ckan/lib/dictization/model_dictize.py @@ -1,9 +1,7 @@ import datetime from pylons import config from sqlalchemy.sql import select -import datetime -import ckan.model -import ckan.misc +import ckan.misc as misc import ckan.logic as logic import ckan.plugins as plugins import ckan.lib.helpers as h @@ -485,7 +483,7 @@ def package_to_api(pkg, context): dictized['license'] = pkg.license.title if pkg.license else None dictized['ratings_average'] = pkg.get_average_rating() dictized['ratings_count'] = len(pkg.ratings) - dictized['notes_rendered'] = ckan.misc.MarkdownFormat().to_html(pkg.notes) + dictized['notes_rendered'] = misc.MarkdownFormat().to_html(pkg.notes) site_url = config.get('ckan.site_url', None) if site_url: diff --git a/ckan/logic/action/create.py b/ckan/logic/action/create.py index ddf0eee5f01..061200a35a4 100644 --- a/ckan/logic/action/create.py +++ b/ckan/logic/action/create.py @@ -104,8 +104,6 @@ def package_create(context, data_dict): ''' model = context['model'] user = context['user'] - model.Session.remove() - model.Session()._context = context package_type = data_dict.get('type') package_plugin = lib_plugins.lookup_package_plugin(package_type) @@ -179,8 +177,6 @@ def package_create(context, data_dict): def package_create_validate(context, data_dict): model = context['model'] schema = lib_plugins.lookup_package_plugin().form_to_db_schema() - model.Session.remove() - model.Session()._context = context _check_access('package_create',context,data_dict) @@ -867,9 +863,6 @@ def vocabulary_create(context, data_dict): model = context['model'] schema = context.get('schema') or ckan.logic.schema.default_create_vocabulary_schema() - model.Session.remove() - model.Session()._context = context - _check_access('vocabulary_create', context, data_dict) data, errors = _validate(data_dict, schema, context) diff --git a/ckan/logic/action/delete.py b/ckan/logic/action/delete.py index 563c9439d45..c104cde1a85 100644 --- a/ckan/logic/action/delete.py +++ b/ckan/logic/action/delete.py @@ -268,8 +268,6 @@ def task_status_delete(context, data_dict): ''' model = context['model'] id = _get_or_bust(data_dict, 'id') - model.Session.remove() - model.Session()._context = context entity = model.TaskStatus.get(id) diff --git a/ckan/logic/action/update.py b/ckan/logic/action/update.py index 8c4585c25ba..7986a6822b0 100644 --- a/ckan/logic/action/update.py +++ b/ckan/logic/action/update.py @@ -106,7 +106,6 @@ def make_latest_pending_package_active(context, data_dict): if not context.get('defer_commit'): session.commit() - session.remove() def related_update(context, data_dict): @@ -128,7 +127,6 @@ def related_update(context, data_dict): id = _get_or_bust(data_dict, "id") schema = context.get('schema') or ckan.logic.schema.default_related_schema() - model.Session.remove() related = model.Related.get(id) context["related"] = related @@ -169,7 +167,6 @@ def resource_update(context, data_dict): user = context['user'] id = _get_or_bust(data_dict, "id") schema = context.get('schema') or ckan.logic.schema.default_update_resource_schema() - model.Session.remove() resource = model.Resource.get(id) context["resource"] = resource @@ -223,8 +220,6 @@ def package_update(context, data_dict): model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] - model.Session.remove() - model.Session()._context = context pkg = model.Package.get(name_or_id) if pkg is None: @@ -295,8 +290,6 @@ def package_update_validate(context, data_dict): user = context['user'] id = _get_or_bust(data_dict, "id") - model.Session.remove() - model.Session()._context = context pkg = model.Package.get(id) context["package"] = pkg diff --git a/ckan/tests/functional/api/model/test_vocabulary.py b/ckan/tests/functional/api/model/test_vocabulary.py index f99e432ff4d..0b23e26f8c9 100644 --- a/ckan/tests/functional/api/model/test_vocabulary.py +++ b/ckan/tests/functional/api/model/test_vocabulary.py @@ -42,6 +42,7 @@ def setup(self): ckan.model.Session.commit() self.sysadmin_user = ckan.model.User.get('admin') self.normal_user = ckan.model.User.get('normal') + self.sysadmin_apikey = self.sysadmin_user.apikey def clean_vocab(self): ckan.model.Session.execute('delete from package_tag_revision') @@ -237,7 +238,7 @@ def test_vocabulary_create_with_tags(self): response = self._post('/api/action/vocabulary_create', params=params, extra_environ = {'Authorization': - str(self.sysadmin_user.apikey)}) + str(self.sysadmin_apikey)}) assert response['success'] == True assert response['result'] created_vocab = response['result'] @@ -284,7 +285,7 @@ def test_vocabulary_create_bad_tags(self): response = self.app.post('/api/action/vocabulary_create', params=json.dumps(params), extra_environ = {'Authorization': - str(self.sysadmin_user.apikey)}, + str(self.sysadmin_apikey)}, status=409) assert response.json['success'] == False assert response.json['error'].has_key('tags') @@ -367,7 +368,7 @@ def test_vocabulary_create_invalid_name(self): response = self.app.post('/api/action/vocabulary_create', params=param_string, extra_environ = {'Authorization': - str(self.sysadmin_user.apikey)}, + str(self.sysadmin_apikey)}, status=409) assert response.json['success'] == False assert response.json['error']['name'] @@ -750,7 +751,7 @@ def test_add_tag_invalid_name(self): response = self.app.post('/api/action/tag_create', params=tag_string, extra_environ = {'Authorization': - str(self.sysadmin_user.apikey)}, + str(self.sysadmin_apikey)}, status=409) assert response.json['success'] == False assert response.json['error']['name'] diff --git a/doc/organizations_and_groups.rst b/doc/organizations_and_groups.rst index 23c6d2e6d83..4518ade38cc 100644 --- a/doc/organizations_and_groups.rst +++ b/doc/organizations_and_groups.rst @@ -80,7 +80,7 @@ User Stories that apply to both Organizations and Groups * **Anyone** can see a list of all the site's organizations. * **Anyone** can see a list of all the site's groups. -* **Anyone** can see a list of all an organization's _public_ datasets +* **Anyone** can see a list of all an organization's _public_ datasets * **Anyone** can see a list of all a group's datasets (groups can't have private datasets, they're all public) * **Sysadmins** can create new organizations, and automatically become admins @@ -141,7 +141,7 @@ organization is specified. Users who are not a member of an organization will be able to add datasets to this default organization. * **Sysadmins** can move datasets from one organization to another. - + * **Sysadmins** can delete organizations, and this deletes all of the organization's datasets. @@ -188,150 +188,53 @@ Technical FAQ The data model will not change from how it is currently:: - + +------------+ | | +---+ dataset | +------------+ +-----------+ | | | | | | +---+ +------------+ - | group +-----+ member | + | group +-----+ member | | | | +---+ +------------+ +------------+ +-----------+ | | | +---+ user | | | +------------+ -The group table has a "type" field specifying if the table is an "organization" -or a "group". +The group table has a "type" field specifying if the table is an "organization" +or a "group". Using the one 'group' table for both organizations and groups means you can't have an organization and a group with the same name. This is probably a good thing as it would be confusing for users anyway. -The member table has field called capacity which should be used as follows: - -* When a dataset is a member of an Organization it must have capacity of - either public/private. -* When a dataset is a member of a Group it must have capacity of 'member'. -* When a user is a member of a Group/Organization it must have capacity - of admin/editor. - - -Transition -========== - - -I'd remove the member table as horrible and move to this model -:: - - - +------------+ - | | - +---+ dataset | - +-----------+ | | | - | group +---+ +------------+ - | ownership | - | +---+ +------------+ - +-----------+ | | | - +---+ group | - | | - +------------+ - - - - +------------+ - | | - +---+ user | - +-----------+ | | | - | group +---+ +------------+ - | membership| - | +---+ +------------+ - +-----------+ | | | - +---+ group | - | | - +------------+ - - +----------------+ - |group_membership| - +----------------+ - |Group/Org | - |User | - |Role | - +----------------+ - - +----------------+ - |group_ownership | - +----------------+ - |Group/Org | - |Dataset | - +----------------+ - -Orgs would just be a group type with it's own forms and a field that -destiguishes it as an org. Probably it's own schema etc - -An organisation would only be different from a group by this type unless I -am given explict differences (note: I have no real knowledge of groups only -that in the code) - -If possible all actions will just be group_.... not organization_.... - -Any changes to the group model would be as minimal as possible - - -Admin -````` - -Need to add some stuff to allow admin of group datasets etc both for -admin/sysadmins - - -Searches -```````` - -Search Indexes would be updated to contain privacy information for groups - -Searches would be updated to not return private data. This may need some -thought to keep things running fast - public users would almost definatly be -a special case as this is a common usage - - -Need methods for group/org applications and admin - -Do we need to move/migrate existing data? - -Group/Org searches should seem different to the user so searching groups -only shows groups etc - -I may need some help with the search stuff - -Auth -```` - -All auth functions would be group_... but these would then internally use -the org_... functionality if the group is an org - -Try to remove any old auth stuff if possible +The member table has field called capacity which should be used as follows: -Permissions to just be hard coded (as user stories) in this first phase but -keep an eye on future upgrades +* When a dataset is a member of an Organization it must have capacity of + 'ozganization'. +* When a dataset is a member of a Group it must have capacity of 'member'. +* When a user is a member of a Group/Organization it must have capacity + of the users role eg. admin, editor, memeber -Sysadmins will have magic powers to see do anything +The package table has gained two new fields -Tests -````` +owner_org - the id of the owning organization +private - determines if the dataset is public or private +` +Config options +============== -Attempt to keep existing tests running and look at some tests for new -functionality. +The following config options have been created. -Misc -```` +ckan.auth.user_create_organizations +ckan.auth.user_create_groups -There will be some integration issues but they are outside the scope of this -doc and the development cycle +ckan.auth.create_user_via_api +ckan.auth.create_dataset_if_not_in_organization -API -``` +ckan.auth.anon_create_dataset +ckan.auth.user_delete_groups -Only actions will be supported for orgs - any v1/2 apis will only work for -groups orgs will 500 +ckan.auth.user_delete_organizations +ckan.auth.create_unowned_dataset