diff --git a/ckanext/datastore/db.py b/ckanext/datastore/db.py index f76b62eedf5..05f9c41b128 100644 --- a/ckanext/datastore/db.py +++ b/ckanext/datastore/db.py @@ -958,7 +958,7 @@ def create(context, data_dict): u'SET LOCAL statement_timeout TO {0}'.format(timeout)) result = context['connection'].execute( u'SELECT * FROM pg_tables WHERE tablename = %s', - data_dict['resource_id'] + data_dict['resource_id'] ).fetchone() if not result: create_table(context, data_dict) @@ -967,6 +967,8 @@ def create(context, data_dict): insert_data(context, data_dict) create_indexes(context, data_dict) create_alias(context, data_dict) + if data_dict.get('private'): + _change_privilege(context, data_dict, 'REVOKE') trans.commit() return _unrename_json_field(data_dict) except IntegrityError, e: @@ -1045,7 +1047,7 @@ def delete(context, data_dict): trans = context['connection'].begin() result = context['connection'].execute( u'SELECT 1 FROM pg_tables WHERE tablename = %s', - data_dict['resource_id'] + data_dict['resource_id'] ).fetchone() if not result: raise ValidationError({ @@ -1138,10 +1140,6 @@ def _get_read_only_user(data_dict): def _change_privilege(context, data_dict, what): - log.info('Changing permissions of resource {0} with {1}'.format( - data_dict['resource_id'], what)) - engine = _get_engine(context, data_dict) - context['connection'] = engine.connect() read_only_user = _get_read_only_user(data_dict) assert(what in ['REVOKE', 'GRANT']) if what == 'REVOKE': @@ -1160,17 +1158,29 @@ def _change_privilege(context, data_dict, what): 'privileges': [u'cannot make "{0}" private'.format( data_dict['resource_id'])], 'info': { - 'orig': [str(e.orig)], + 'orig': str(e.orig), 'pgcode': e.orig.pgcode } }) - finally: - context['connection'].close() def make_private(context, data_dict): - _change_privilege(context, data_dict, 'REVOKE') + log.info('Making resource {0} privtae'.format( + data_dict['resource_id'])) + engine = _get_engine(context, data_dict) + context['connection'] = engine.connect() + try: + _change_privilege(context, data_dict, 'REVOKE') + finally: + context['connection'].close() def make_public(context, data_dict): - _change_privilege(context, data_dict, 'GRANT') + log.info('Making resource {0} public'.format( + data_dict['resource_id'])) + engine = _get_engine(context, data_dict) + context['connection'] = engine.connect() + try: + _change_privilege(context, data_dict, 'GRANT') + finally: + context['connection'].close() diff --git a/ckanext/datastore/logic/action.py b/ckanext/datastore/logic/action.py index 5531954a7d8..a53c1ef0c03 100644 --- a/ckanext/datastore/logic/action.py +++ b/ckanext/datastore/logic/action.py @@ -71,8 +71,14 @@ def datastore_create(context, data_dict): 'alias': ['{0} is not a valid alias name'.format(alias)] }) + # create a private datastore resource, if necessary + resource = model.Resource.get(res_id) + if resource.resource_group.package.private: + data_dict['private'] = True + result = db.create(context, data_dict) result.pop('id', None) + result.pop('private', None) result.pop('connection_url') return result diff --git a/ckanext/datastore/plugin.py b/ckanext/datastore/plugin.py index bbce78149ec..9c9deb222a6 100644 --- a/ckanext/datastore/plugin.py +++ b/ckanext/datastore/plugin.py @@ -20,6 +20,7 @@ class DatastorePlugin(p.SingletonPlugin): p.implements(p.IConfigurable, inherit=True) p.implements(p.IActions) p.implements(p.IAuthFunctions) + p.implements(p.IDomainObjectModification, inherit=True) legacy_mode = False @@ -100,6 +101,26 @@ def new_resource_show(context, data_dict): new_resource_show._datastore_wrapped = True logic._actions['resource_show'] = new_resource_show + def notify(self, entity, operation): + if not isinstance(entity, model.Package) or self.legacy_mode: + return + # if a resource is new, it cannot have a datastore resource, yet + if operation == model.domain_object.DomainObjectOperation.changed: + context = {'model': model, 'ignore_auth': True, 'validate': False} + if entity.private: + func = p.toolkit.get_action('datastore_make_private') + else: + func = p.toolkit.get_action('datastore_make_public') + for resource in entity.resources: + try: + func(context, { + 'connection_url': self.write_url, + 'resource_id': resource.id}) + except p.toolkit.ObjectNotFound: + pass + elif operation == model.domain_object.DomainObjectOperation.deleted: + pass # TODO: delete datastore resource + def _log_or_raise(self, message): if self.config.get('debug'): log.critical(message)