diff --git a/ckanext/datavicmain/logic/action.py b/ckanext/datavicmain/logic/action.py index e6bd911..e656232 100644 --- a/ckanext/datavicmain/logic/action.py +++ b/ckanext/datavicmain/logic/action.py @@ -6,32 +6,25 @@ import ckanapi from sqlalchemy import or_ +import ckan.lib.plugins as lib_plugins import ckan.model as model import ckan.types as types import ckan.plugins.toolkit as toolkit -from ckanext.datavicmain import helpers, utils, const, jobs -from ckanext.datavicmain.helpers import user_is_registering -from ckanext.datavicmain.logic.schema import custom_user_create_schema - -import ckan.lib.plugins as lib_plugins -import ckan.plugins.toolkit as toolkit from ckan.common import g -from ckan.lib.dictization import model_dictize, model_save -from ckan.lib.navl.validators import not_empty -from ckan.logic import schema as ckan_schema, validate -from ckan.model import State +from ckan.logic import validate from ckan.types import Action, Context, DataDict from ckan.types.logic import ActionResult +from ckanext.syndicate.utils import get_profiles, get_target from ckanext.mailcraft.utils import get_mailer from ckanext.mailcraft.exception import MailerException -import ckanext.datavic_iar_theme.helpers as theme_helpers +from ckanext.datavicmain import helpers, utils, const from ckanext.datavicmain.logic import schema as vic_schema + log = logging.getLogger(__name__) -user_is_registering = helpers.user_is_registering ValidationError = toolkit.ValidationError get_action = toolkit.get_action _validate = toolkit.navl_validate @@ -45,12 +38,12 @@ @toolkit.chained_action def user_create(next_func, context, data_dict): """Create a pending user on registration""" - is_registration = user_is_registering() + is_registration = helpers.user_is_registering() if not is_registration: return next_func(context, data_dict) - context["schema"] = custom_user_create_schema() + context["schema"] = vic_schema.custom_user_create_schema() user_dict = next_func(context, data_dict) data_dict["user_id"] = user_dict["id"] @@ -64,20 +57,34 @@ def user_create(next_func, context, data_dict): @toolkit.chained_action def organization_update(next_, context, data_dict): - from ckanext.syndicate import utils - + """ + Add organization fields synchronization logic. + Add prohibition on changing the organization visibility field. + """ model = context["model"] old = model.Group.get(data_dict.get("id")) old_name = old.name if old else None + old_visibility = model.Group.get(data_dict["id"]).extras.get( + const.ORG_VISIBILITY_FIELD, const.ORG_VISIBILITY_DEFAULT + ) result = next_(context, data_dict) - if old_name == result["name"]: + org_id = result["id"] + new_name = result["name"] + new_visibility = utils.get_extra_value(const.ORG_VISIBILITY_FIELD, result) + + if new_visibility != old_visibility: + raise ValidationError( + f"The organisation {org_id} visibility can't be changed after creation." + ) + + if old_name == new_name: return result - for profile in utils.get_profiles(): - ckan = utils.get_target(profile.ckan_url, profile.api_key) + for profile in get_profiles(): + ckan = get_target(profile.ckan_url, profile.api_key) try: remote = ckan.action.organization_show(id=old_name) except ckanapi.NotFound: @@ -114,35 +121,6 @@ def organization_show( return org_dict -@toolkit.chained_action -def organization_update( - next_: types.ChainedAction, - context: types.Context, - data_dict: types.DataDict, -) -> types.ActionResult.OrganizationUpdate: - """Changing visibility field should change the visibility datasets. We are - using permissions labels, so we have to reindex all the datasets to index - new labels into solr""" - current_visibility = model.Group.get(data_dict["id"]).extras.get( - const.ORG_VISIBILITY_FIELD, const.ORG_VISIBILITY_DEFAULT - ) - - org_dict = next_(context, data_dict) - - new_visibility = utils.get_extra_value( - const.ORG_VISIBILITY_FIELD, org_dict - ) - - if new_visibility != current_visibility: - log.info( - "The organisation %s visibility has changed. Rebuilding datasets index", - org_dict["id"], - ) - toolkit.enqueue_job(jobs.reindex_organization, [org_dict["id"]]) - - return org_dict - - @toolkit.chained_action @toolkit.side_effect_free def organization_list( @@ -262,7 +240,7 @@ def datavic_list_incomplete_resources(context, data_dict): missing_conditions = [] for field in required_fields: model_attr = getattr(model.Resource, field) - missing_conditions.append(or_(model_attr == None, model_attr == "")) + missing_conditions.append(or_(model_attr is None, model_attr == "")) q = ( model.Session.query(model.Resource) diff --git a/ckanext/datavicmain/logic/validators.py b/ckanext/datavicmain/logic/validators.py index 7a52af1..56a0633 100644 --- a/ckanext/datavicmain/logic/validators.py +++ b/ckanext/datavicmain/logic/validators.py @@ -178,3 +178,49 @@ def datavic_private_validator( not suitable for public release""" ) return + + +def datavic_organization_parent_validator( + key: types.FlattenKey, + data: types.FlattenDataDict, + errors: types.FlattenErrorDict, + context: types.Context, +) -> Any: + """ + Restricted organization can't be assigned as a child of unrestricted one + or vice versa + """ + value = data.get(("groups", 0, "name")) + visibility = data.get(("visibility",)) == "restricted" + model = context["model"] + parent = model.Group.get(value) + if parent: + is_restricted = tk.h.datavic_is_org_restricted(parent.id) + if (is_restricted and not visibility) or \ + (not is_restricted and visibility): + errors[("parent",)].append( + """Incorrect value - restricted organization can't be assigned + as a child of unrestricted one or vice versa""" + ) + return + + +def datavic_set_org_visibility_if_new( + key: types.FlattenKey, + data: types.FlattenDataDict, + errors: types.FlattenErrorDict, + context: types.Context, +) -> Any: + """ + The field can be set at creation stage only + """ + blueprint, endpoint = tk.get_endpoint() + if blueprint == "organization" and endpoint == "edit": + model = context["model"] + old_value = model.Group.get(data[("name",)]).extras.get("visibility") + new_value = data[key] + if old_value != new_value: + errors[key].append( + """Incorrect value - the field can be set at creation stage only""" + ) + return diff --git a/ckanext/datavicmain/organisation_schema.yaml b/ckanext/datavicmain/organisation_schema.yaml index d33769d..39cba90 100644 --- a/ckanext/datavicmain/organisation_schema.yaml +++ b/ckanext/datavicmain/organisation_schema.yaml @@ -34,7 +34,7 @@ fields: form_snippet: vic_org_visibility.html required: true help_text: Restricted organisations, their datasets and their child organisations are only visible to members of that organisation. - validators: default(unrestricted) + validators: datavic_set_org_visibility_if_new default(unrestricted) choices: - value: unrestricted label: Unrestricted @@ -44,5 +44,5 @@ fields: - field_name: parent label: Parent form_snippet: org_hierarchy.html - validators: ignore_empty + validators: datavic_organization_parent_validator unicode_safe required: true