diff --git a/backend/dataall/core/permissions/services/resource_policy_service.py b/backend/dataall/core/permissions/services/resource_policy_service.py
index 95de63743..c39c354d4 100644
--- a/backend/dataall/core/permissions/services/resource_policy_service.py
+++ b/backend/dataall/core/permissions/services/resource_policy_service.py
@@ -217,6 +217,7 @@ def get_resource_policy_permissions(session, group_uri, resource_uri) -> List[Re
raise exceptions.RequiredParameter(param_name='group_uri')
if not resource_uri:
raise exceptions.RequiredParameter(param_name='resource_uri')
+
policy = ResourcePolicyRepository.find_resource_policy(
session=session,
group_uri=group_uri,
diff --git a/backend/dataall/modules/metadata_forms/api/queries.py b/backend/dataall/modules/metadata_forms/api/queries.py
index 4458e3860..e9385e091 100644
--- a/backend/dataall/modules/metadata_forms/api/queries.py
+++ b/backend/dataall/modules/metadata_forms/api/queries.py
@@ -5,6 +5,7 @@
get_metadata_form,
get_attached_metadata_form,
list_attached_forms,
+ get_entity_metadata_form_permissions,
)
listUserMetadataForms = gql.QueryField(
@@ -47,3 +48,11 @@
resolver=get_attached_metadata_form,
test_scope='MetadataForm',
)
+
+getEntityMetadataFormPermissions = gql.QueryField(
+ name='getEntityMetadataFormPermissions',
+ args=[gql.Argument('entityUri', gql.NonNullableType(gql.String))],
+ type=gql.ArrayType(gql.String),
+ resolver=get_entity_metadata_form_permissions,
+ test_scope='MetadataForm',
+)
diff --git a/backend/dataall/modules/metadata_forms/api/resolvers.py b/backend/dataall/modules/metadata_forms/api/resolvers.py
index 390a0938f..4e03e6d6c 100644
--- a/backend/dataall/modules/metadata_forms/api/resolvers.py
+++ b/backend/dataall/modules/metadata_forms/api/resolvers.py
@@ -94,3 +94,7 @@ def has_tenant_permissions_for_metadata_forms(context: Context, source: Metadata
def resolve_metadata_form_field(context: Context, source: AttachedMetadataFormField):
return MetadataFormService.get_metadata_form_field_by_uri(uri=source.fieldUri)
+
+
+def get_entity_metadata_form_permissions(context: Context, source, entityUri):
+ return MetadataFormService.get_mf_permissions(entityUri=entityUri)
diff --git a/backend/dataall/modules/metadata_forms/db/metadata_form_repository.py b/backend/dataall/modules/metadata_forms/db/metadata_form_repository.py
index cd404e396..8dcf55f1b 100644
--- a/backend/dataall/modules/metadata_forms/db/metadata_form_repository.py
+++ b/backend/dataall/modules/metadata_forms/db/metadata_form_repository.py
@@ -70,6 +70,9 @@ def query_user_metadata_forms(session, is_da_admin, groups, env_uris, org_uris,
:param filter:
"""
+ env_uris = env_uris or []
+ org_uris = org_uris or []
+
query = session.query(MetadataForm)
if not is_da_admin:
@@ -141,16 +144,22 @@ def query_entity_metadata_forms(
entity_orgs_uris = entity_orgs_uris or []
entity_envs_uris = entity_envs_uris or []
- orgs = list(set(user_org_uris).intersection(set(entity_orgs_uris)))
- envs = list(set(user_env_uris).intersection(set(entity_envs_uris)))
-
- query = MetadataFormRepository.query_user_metadata_forms(session, is_da_admin, groups, envs, orgs, filter)
-
- if not orgs:
- query = query.filter(MetadataForm.visibility != MetadataFormVisibility.Organization.value)
+ query = MetadataFormRepository.query_user_metadata_forms(
+ session, is_da_admin, groups, user_env_uris, user_org_uris, filter
+ )
- if not envs:
- query = query.filter(MetadataForm.visibility != MetadataFormVisibility.Environment.value)
+ query = query.filter(
+ and_(
+ or_(
+ MetadataForm.visibility != MetadataFormVisibility.Organization.value,
+ MetadataForm.homeEntity.in_(entity_orgs_uris),
+ ),
+ or_(
+ MetadataForm.visibility != MetadataFormVisibility.Environment.value,
+ MetadataForm.homeEntity.in_(entity_envs_uris),
+ ),
+ )
+ )
query = MetadataFormRepository.exclude_attached(session, query, filter)
return query.order_by(MetadataForm.name)
@@ -247,3 +256,9 @@ def query_attached_metadata_forms(session, is_da_admin, groups, user_envs_uris,
if filter and filter.get('metadataFormUri'):
query = query.filter(AttachedMetadataForm.metadataFormUri == filter.get('metadataFormUri'))
return query
+
+ @staticmethod
+ def query_all_attached_metadata_forms_for_entity(session, entityUri, entityType):
+ return session.query(AttachedMetadataForm).filter(
+ and_(AttachedMetadataForm.entityType == entityType, AttachedMetadataForm.entityUri == entityUri)
+ )
diff --git a/backend/dataall/modules/metadata_forms/services/attached_metadata_form_service.py b/backend/dataall/modules/metadata_forms/services/attached_metadata_form_service.py
index 41f6067b4..005e9a45b 100644
--- a/backend/dataall/modules/metadata_forms/services/attached_metadata_form_service.py
+++ b/backend/dataall/modules/metadata_forms/services/attached_metadata_form_service.py
@@ -1,10 +1,9 @@
from dataall.base.context import get_context
from dataall.base.db import exceptions, paginate
-from dataall.core.environment.db.environment_repositories import EnvironmentRepository
-from dataall.core.organizations.db.organization_repositories import OrganizationRepository
-from dataall.core.permissions.services.tenant_policy_service import TenantPolicyValidationService
+from dataall.core.permissions.services.resource_policy_service import ResourcePolicyService
from dataall.modules.metadata_forms.db.metadata_form_repository import MetadataFormRepository
from dataall.modules.metadata_forms.services.metadata_form_access_service import MetadataFormAccessService
+from dataall.modules.metadata_forms.services.metadata_form_permissions import ATTACH_METADATA_FORM
class AttachedMetadataFormValidationService:
@@ -33,15 +32,22 @@ def validate_enrich_fields_params(mf_fields, data):
class AttachedMetadataFormService:
@staticmethod
+ def _get_entity_uri(data):
+ return data.get('entityUri')
+
+ @staticmethod
+ @ResourcePolicyService.has_resource_permission(
+ ATTACH_METADATA_FORM, parent_resource=_get_entity_uri, param_name='data'
+ )
def create_attached_metadata_form(uri, data):
AttachedMetadataFormValidationService.validate_filled_form_params(uri, data)
- with get_context().db_engine.scoped_session() as session:
+ context = get_context()
+ with context.db_engine.scoped_session() as session:
mf = MetadataFormRepository.get_metadata_form(session, uri)
if not mf:
raise exceptions.ObjectNotFound('MetadataForm', uri)
mf_fields = MetadataFormRepository.get_metadata_form_fields(session, uri)
AttachedMetadataFormValidationService.validate_enrich_fields_params(mf_fields, data)
-
amf = MetadataFormRepository.create_attached_metadata_form(session, uri, data)
for f in data.get('fields'):
MetadataFormRepository.create_attached_metadata_form_field(
@@ -74,7 +80,11 @@ def list_attached_forms(filter=None):
).to_dict()
@staticmethod
+ @ResourcePolicyService.has_resource_permission(
+ ATTACH_METADATA_FORM, parent_resource=_get_entity_uri, param_name='data'
+ )
def delete_attached_metadata_form(uri):
mf = AttachedMetadataFormService.get_attached_metadata_form(uri)
- with get_context().db_engine.scoped_session() as session:
+ context = get_context()
+ with context.db_engine.scoped_session() as session:
return session.delete(mf)
diff --git a/backend/dataall/modules/metadata_forms/services/metadata_form_permissions.py b/backend/dataall/modules/metadata_forms/services/metadata_form_permissions.py
index f5801f6e3..883977a16 100644
--- a/backend/dataall/modules/metadata_forms/services/metadata_form_permissions.py
+++ b/backend/dataall/modules/metadata_forms/services/metadata_form_permissions.py
@@ -1,6 +1,55 @@
+from dataall.core.permissions.services.environment_permissions import ENVIRONMENT_INVITED, ENVIRONMENT_ALL
+from dataall.core.permissions.services.organization_permissions import (
+ ORGANIZATION_ALL,
+ ORGANIZATION_INVITED_DESCRIPTIONS,
+)
from dataall.core.permissions.services.tenant_permissions import TENANT_ALL, TENANT_ALL_WITH_DESC
+from dataall.core.permissions.services.resources_permissions import RESOURCES_ALL, RESOURCES_ALL_WITH_DESC
+from dataall.modules.s3_datasets.services.dataset_permissions import DATASET_WRITE, DATASET_ALL
-
+# ------------------------TENANT-----------------------------------
MANAGE_METADATA_FORMS = 'MANAGE_METADATA_FORMS'
TENANT_ALL.append(MANAGE_METADATA_FORMS)
TENANT_ALL_WITH_DESC[MANAGE_METADATA_FORMS] = 'Manage metadata forms'
+
+# ------------------------RESOURCE---------------------------------
+# permissions to attach MF to the entity, ot make the entity the visibility base for MF
+# these permissions are attached to Organizations, Environments, Datasets etc.
+ATTACH_METADATA_FORM = 'ATTACH_METADATA_FORM'
+CREATE_METADATA_FORM = 'CREATE_METADATA_FORM'
+ALL_METADATA_FORMS_ENTITY_PERMISSIONS = [ATTACH_METADATA_FORM, CREATE_METADATA_FORM]
+RESOURCES_ALL.extend(ALL_METADATA_FORMS_ENTITY_PERMISSIONS)
+RESOURCES_ALL_WITH_DESC[CREATE_METADATA_FORM] = 'Create metadata form within this visibility scope'
+RESOURCES_ALL_WITH_DESC[ATTACH_METADATA_FORM] = 'Attach metadata form'
+
+ORGANIZATION_ALL.extend(ALL_METADATA_FORMS_ENTITY_PERMISSIONS)
+ORGANIZATION_INVITED_DESCRIPTIONS[CREATE_METADATA_FORM] = 'Create metadata form within this visibility scope'
+ORGANIZATION_INVITED_DESCRIPTIONS[ATTACH_METADATA_FORM] = 'Attach metadata form'
+
+ENVIRONMENT_INVITED.extend(ALL_METADATA_FORMS_ENTITY_PERMISSIONS)
+ENVIRONMENT_ALL.extend(ALL_METADATA_FORMS_ENTITY_PERMISSIONS)
+
+DATASET_WRITE.extend(ALL_METADATA_FORMS_ENTITY_PERMISSIONS)
+DATASET_ALL.extend(ALL_METADATA_FORMS_ENTITY_PERMISSIONS)
+# ------------------------METADATA FORM----------------------------
+# permissions to change and delete metadata forms
+# these permissions are attached to MFs
+UPDATE_METADATA_FORM_FIELD = 'UPDATE_METADATA_FORM_FIELD'
+DELETE_METADATA_FORM_FIELD = 'DELETE_METADATA_FORM_FIELD'
+DELETE_METADATA_FORM = 'DELETE_METADATA_FORM'
+EDIT_METADATA_FORM = 'EDIT_METADATA_FORM'
+
+METADATA_FORM_PERMISSIONS_ALL = [
+ UPDATE_METADATA_FORM_FIELD,
+ DELETE_METADATA_FORM_FIELD,
+ DELETE_METADATA_FORM,
+ EDIT_METADATA_FORM,
+]
+
+METADATA_FORM_EDIT_PERMISSIONS = [
+ EDIT_METADATA_FORM,
+ UPDATE_METADATA_FORM_FIELD,
+ DELETE_METADATA_FORM_FIELD,
+]
+
+RESOURCES_ALL.extend(METADATA_FORM_PERMISSIONS_ALL)
diff --git a/backend/dataall/modules/metadata_forms/services/metadata_form_service.py b/backend/dataall/modules/metadata_forms/services/metadata_form_service.py
index ac4ddbb91..5ac4af784 100644
--- a/backend/dataall/modules/metadata_forms/services/metadata_form_service.py
+++ b/backend/dataall/modules/metadata_forms/services/metadata_form_service.py
@@ -2,7 +2,9 @@
from dataall.base.db import exceptions, paginate
from dataall.core.organizations.db.organization_repositories import OrganizationRepository
from dataall.core.environment.db.environment_repositories import EnvironmentRepository
-from dataall.core.permissions.services.tenant_policy_service import TenantPolicyValidationService, TenantPolicyService
+from dataall.core.permissions.db.resource_policy.resource_policy_repositories import ResourcePolicyRepository
+from dataall.core.permissions.services.resource_policy_service import ResourcePolicyService
+from dataall.core.permissions.services.tenant_policy_service import TenantPolicyService
from dataall.modules.metadata_forms.db.enums import (
MetadataFormVisibility,
MetadataFormFieldType,
@@ -10,7 +12,14 @@
from dataall.modules.catalog.db.glossary_repositories import GlossaryRepository
from dataall.modules.metadata_forms.db.metadata_form_repository import MetadataFormRepository
from dataall.modules.metadata_forms.services.metadata_form_access_service import MetadataFormAccessService
-from dataall.modules.metadata_forms.services.metadata_form_permissions import MANAGE_METADATA_FORMS
+from dataall.modules.metadata_forms.services.metadata_form_permissions import (
+ MANAGE_METADATA_FORMS,
+ DELETE_METADATA_FORM,
+ DELETE_METADATA_FORM_FIELD,
+ UPDATE_METADATA_FORM_FIELD,
+ CREATE_METADATA_FORM,
+ ALL_METADATA_FORMS_ENTITY_PERMISSIONS,
+)
class MetadataFormParamValidationService:
@@ -91,7 +100,20 @@ class MetadataFormService:
@TenantPolicyService.has_tenant_permission(MANAGE_METADATA_FORMS)
def create_metadata_form(data):
MetadataFormParamValidationService.validate_create_form_params(data)
- with get_context().db_engine.scoped_session() as session:
+ context = get_context()
+ with context.db_engine.scoped_session() as session:
+ if data.get('visibility') in [
+ MetadataFormVisibility.Organization.value,
+ MetadataFormVisibility.Environment.value,
+ ]:
+ ResourcePolicyService.check_user_resource_permission(
+ session=session,
+ username=context.username,
+ groups=context.groups,
+ resource_uri=data.get('homeEntity'),
+ permission_name=CREATE_METADATA_FORM,
+ )
+
form = MetadataFormRepository.create_metadata_form(session, data)
return form
@@ -104,7 +126,7 @@ def get_metadata_form_by_uri(uri):
# toDo: deletion logic
@staticmethod
@TenantPolicyService.has_tenant_permission(MANAGE_METADATA_FORMS)
- @MetadataFormAccessService.can_perform('DELETE')
+ @MetadataFormAccessService.can_perform(DELETE_METADATA_FORM)
def delete_metadata_form_by_uri(uri):
if mf := MetadataFormService.get_metadata_form_by_uri(uri):
with get_context().db_engine.scoped_session() as session:
@@ -181,7 +203,7 @@ def get_metadata_form_field_by_uri(uri):
@staticmethod
@TenantPolicyService.has_tenant_permission(MANAGE_METADATA_FORMS)
- @MetadataFormAccessService.can_perform('ADD FIELD')
+ @MetadataFormAccessService.can_perform(UPDATE_METADATA_FORM_FIELD)
def create_metadata_form_field(uri, data):
MetadataFormParamValidationService.validate_create_field_params(data)
with get_context().db_engine.scoped_session() as session:
@@ -189,7 +211,7 @@ def create_metadata_form_field(uri, data):
@staticmethod
@TenantPolicyService.has_tenant_permission(MANAGE_METADATA_FORMS)
- @MetadataFormAccessService.can_perform('ADD FIELDS')
+ @MetadataFormAccessService.can_perform(UPDATE_METADATA_FORM_FIELD)
def create_metadata_form_fields(uri, data_arr):
fields = []
for data in data_arr:
@@ -198,7 +220,7 @@ def create_metadata_form_fields(uri, data_arr):
@staticmethod
@TenantPolicyService.has_tenant_permission(MANAGE_METADATA_FORMS)
- @MetadataFormAccessService.can_perform('DELETE FIELD')
+ @MetadataFormAccessService.can_perform(DELETE_METADATA_FORM_FIELD)
def delete_metadata_form_field(uri, fieldUri):
mf = MetadataFormService.get_metadata_form_field_by_uri(fieldUri)
with get_context().db_engine.scoped_session() as session:
@@ -206,7 +228,7 @@ def delete_metadata_form_field(uri, fieldUri):
@staticmethod
@TenantPolicyService.has_tenant_permission(MANAGE_METADATA_FORMS)
- @MetadataFormAccessService.can_perform('UPDATE FIELDS')
+ @MetadataFormAccessService.can_perform('UPDATE_METADATA_FORM_FIELD')
def batch_metadata_form_field_update(uri, data):
to_delete = []
to_update = []
@@ -238,8 +260,23 @@ def batch_metadata_form_field_update(uri, data):
@staticmethod
@TenantPolicyService.has_tenant_permission(MANAGE_METADATA_FORMS)
- @MetadataFormAccessService.can_perform('UPDATE FIELD')
+ @MetadataFormAccessService.can_perform(UPDATE_METADATA_FORM_FIELD)
def update_metadata_form_field(uri, fieldUri, data):
with get_context().db_engine.scoped_session() as session:
MetadataFormParamValidationService.validate_update_field_params(uri, data)
return MetadataFormRepository.update_metadata_form_field(session, fieldUri, data)
+
+ @staticmethod
+ def get_mf_permissions(entityUri):
+ context = get_context()
+ result_permissions = []
+ with context.db_engine.scoped_session() as session:
+ for permissions in ALL_METADATA_FORMS_ENTITY_PERMISSIONS:
+ if ResourcePolicyRepository.has_user_resource_permission(
+ session=session,
+ groups=context.groups,
+ permission_name=permissions,
+ resource_uri=entityUri,
+ ):
+ result_permissions.append(permissions)
+ return result_permissions
diff --git a/backend/dataall/modules/redshift_datasets/services/redshift_dataset_service.py b/backend/dataall/modules/redshift_datasets/services/redshift_dataset_service.py
index 2edf3724c..f578894b0 100644
--- a/backend/dataall/modules/redshift_datasets/services/redshift_dataset_service.py
+++ b/backend/dataall/modules/redshift_datasets/services/redshift_dataset_service.py
@@ -193,6 +193,7 @@ def delete_redshift_dataset(uri):
RedshiftDatasetService._delete_dataset_term_links(session, uri)
VoteRepository.delete_votes(session, dataset.datasetUri, VOTE_REDSHIFT_DATASET_NAME)
session.delete(dataset)
+
session.commit()
return True
diff --git a/backend/dataall/modules/s3_datasets/services/dataset_service.py b/backend/dataall/modules/s3_datasets/services/dataset_service.py
index 14cfdc2fd..2e68eb951 100644
--- a/backend/dataall/modules/s3_datasets/services/dataset_service.py
+++ b/backend/dataall/modules/s3_datasets/services/dataset_service.py
@@ -22,7 +22,6 @@
from dataall.modules.catalog.db.glossary_repositories import GlossaryRepository
from dataall.modules.s3_datasets.db.dataset_bucket_repositories import DatasetBucketRepository
from dataall.modules.shares_base.db.share_object_repositories import ShareObjectRepository
-from dataall.modules.shares_base.services.share_object_service import ShareObjectService
from dataall.modules.vote.db.vote_repositories import VoteRepository
from dataall.modules.s3_datasets.aws.glue_dataset_client import DatasetCrawler
from dataall.modules.s3_datasets.aws.s3_dataset_client import S3DatasetClient
diff --git a/backend/migrations/versions/075d344ae2cc_mf_triggers.py b/backend/migrations/versions/075d344ae2cc_mf_triggers.py
new file mode 100644
index 000000000..35b1a9b5e
--- /dev/null
+++ b/backend/migrations/versions/075d344ae2cc_mf_triggers.py
@@ -0,0 +1,153 @@
+"""mf_triggers
+
+Revision ID: 075d344ae2cc
+Revises: 427db8f31999
+Create Date: 2024-09-13 13:12:16.951311
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+# revision identifiers, used by Alembic.
+revision = '075d344ae2cc'
+down_revision = '427db8f31999'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.execute("""
+ CREATE OR REPLACE FUNCTION org_delete_trigger_function()
+ RETURNS TRIGGER AS $$
+ BEGIN
+ -- Delete from attached_metadata_form
+ DELETE FROM attached_metadata_form
+ WHERE "entityUri" = OLD."organizationUri"
+ AND "entityType" = 'Organization';
+
+ -- Delete from metadata_form
+ DELETE FROM metadata_form
+ WHERE "homeEntity" = OLD."organizationUri"
+ AND visibility = 'Organization-Wide';
+
+ RETURN OLD;
+ END;
+ $$ LANGUAGE plpgsql;
+
+ -- Create the trigger for organization table
+ CREATE TRIGGER org_delete_trigger
+ BEFORE DELETE ON organization
+ FOR EACH ROW
+ EXECUTE FUNCTION org_delete_trigger_function();
+ """)
+
+ op.execute("""
+ CREATE OR REPLACE FUNCTION env_delete_trigger_function()
+ RETURNS TRIGGER AS $$
+ BEGIN
+ -- Delete from attached_metadata_form
+ DELETE FROM attached_metadata_form
+ WHERE "entityUri" = OLD."environmentUri"
+ AND "entityType" = 'Environment';
+
+ -- Delete from metadata_form
+ DELETE FROM metadata_form
+ WHERE "homeEntity" = OLD."environmentUri"
+ AND visibility = 'Environment-Wide';
+
+ RETURN OLD;
+ END;
+ $$ LANGUAGE plpgsql;
+
+ -- Create the trigger for environment table
+ CREATE TRIGGER env_delete_trigger
+ BEFORE DELETE ON environment
+ FOR EACH ROW
+ EXECUTE FUNCTION env_delete_trigger_function();
+ """)
+
+ op.execute("""
+ CREATE OR REPLACE FUNCTION dataset_delete_trigger_function()
+ RETURNS TRIGGER AS $$
+ BEGIN
+ -- Delete from attached_metadata_form
+ DELETE FROM attached_metadata_form
+ WHERE "entityUri" = OLD."datasetUri"
+ AND "entityType" = 'Dataset';
+
+ RETURN OLD;
+ END;
+ $$ LANGUAGE plpgsql;
+
+ -- Create the trigger for dataset table
+ CREATE TRIGGER dataset_delete_trigger
+ BEFORE DELETE ON dataset
+ FOR EACH ROW
+ EXECUTE FUNCTION dataset_delete_trigger_function();
+ """)
+
+ op.execute("""
+ CREATE OR REPLACE FUNCTION metadata_form_delete_trigger_function()
+ RETURNS TRIGGER AS $$
+ BEGIN
+ -- Delete from resource_permission_policy
+ DELETE FROM resource_policy_permission
+ WHERE "sid" in (SELECT sid from resource_policy where "resourceUri"=OLD.uri and "resourceType"='MetadataForm');
+ DELETE FROM resource_policy where "resourceUri"=OLD.uri;
+ RETURN OLD;
+ END;
+ $$ LANGUAGE plpgsql;
+
+ -- Create the trigger for dataset table
+ CREATE TRIGGER metadata_form_delete_trigger
+ BEFORE DELETE ON metadata_form
+ FOR EACH ROW
+ EXECUTE FUNCTION metadata_form_delete_trigger_function();
+ """)
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.execute(
+ """
+ -- Drop the org_delete_trigger
+ DROP TRIGGER IF EXISTS org_delete_trigger ON organization;
+
+ -- Drop the org_delete_trigger_function
+ DROP FUNCTION IF EXISTS org_delete_trigger_function;
+ """
+ )
+
+ op.execute(
+ """
+ -- Drop the env_delete_trigger
+ DROP TRIGGER IF EXISTS env_delete_trigger ON environment;
+
+ -- Drop the env_delete_trigger_function
+ DROP FUNCTION IF EXISTS env_delete_trigger_function;
+ """
+ )
+
+ op.execute(
+ """
+ -- Drop the dataset_delete_trigger
+ DROP TRIGGER IF EXISTS dataset_delete_trigger ON dataset;
+
+ -- Drop the dataset_delete_trigger_function
+ DROP FUNCTION IF EXISTS dataset_delete_trigger_function;
+ """
+ )
+
+ op.execute(
+ """
+ -- Drop the dataset_delete_trigger
+ DROP TRIGGER IF EXISTS metadata_form_delete_trigger ON metadata_form;
+
+ -- Drop the dataset_delete_trigger_function
+ DROP FUNCTION IF EXISTS metadata_form_delete_trigger_function;
+ """
+ )
+ # ### end Alembic commands ###
diff --git a/backend/migrations/versions/427db8f31999_backfill_MF_resource_permissions.py b/backend/migrations/versions/427db8f31999_backfill_MF_resource_permissions.py
new file mode 100644
index 000000000..5209963e8
--- /dev/null
+++ b/backend/migrations/versions/427db8f31999_backfill_MF_resource_permissions.py
@@ -0,0 +1,127 @@
+"""backfill_MF_resource_permissions
+
+Revision ID: 427db8f31999
+Revises: f87aecc36d39
+Create Date: 2024-09-11 15:55:51.444403
+
+"""
+
+from alembic import op
+from sqlalchemy import orm
+
+from dataall.core.environment.db.environment_models import Environment
+from dataall.core.organizations.db.organization_models import Organization
+from dataall.core.permissions.api.enums import PermissionType
+from dataall.core.permissions.services.permission_service import PermissionService
+from dataall.core.permissions.services.resource_policy_service import ResourcePolicyService
+from dataall.core.permissions.services.resources_permissions import RESOURCES_ALL_WITH_DESC
+from dataall.modules.datasets_base.db.dataset_models import DatasetBase
+from dataall.modules.metadata_forms.services.metadata_form_permissions import (
+ ATTACH_METADATA_FORM,
+ CREATE_METADATA_FORM,
+ METADATA_FORM_PERMISSIONS_ALL,
+)
+
+# revision identifiers, used by Alembic.
+revision = '427db8f31999'
+down_revision = 'f87aecc36d39'
+branch_labels = None
+depends_on = None
+
+
+def get_session():
+ bind = op.get_bind()
+ session = orm.Session(bind=bind)
+ return session
+
+
+def upgrade():
+ session = get_session()
+
+ for perm in [ATTACH_METADATA_FORM, CREATE_METADATA_FORM] + METADATA_FORM_PERMISSIONS_ALL:
+ PermissionService.save_permission(
+ session,
+ name=perm,
+ description=RESOURCES_ALL_WITH_DESC.get(perm, perm),
+ permission_type=PermissionType.RESOURCE.name,
+ )
+ print('Adding organization resource permissions...')
+ orgs = session.query(Organization).all()
+ for org in orgs:
+ ResourcePolicyService.attach_resource_policy(
+ session=session,
+ group=org.SamlGroupName,
+ resource_uri=org.organizationUri,
+ permissions=[ATTACH_METADATA_FORM, CREATE_METADATA_FORM],
+ resource_type=Organization.__name__,
+ )
+ print('Adding environment resource permissions...')
+ envs = session.query(Environment).all()
+ for env in envs:
+ ResourcePolicyService.attach_resource_policy(
+ session=session,
+ group=env.SamlGroupName,
+ resource_uri=env.environmentUri,
+ permissions=[ATTACH_METADATA_FORM, CREATE_METADATA_FORM],
+ resource_type=Environment.__name__,
+ )
+ print('Adding dataset resource permissions...')
+ datasets = session.query(DatasetBase).all()
+ for dataset in datasets:
+ ResourcePolicyService.attach_resource_policy(
+ session=session,
+ group=dataset.SamlAdminGroupName,
+ resource_uri=dataset.datasetUri,
+ permissions=[ATTACH_METADATA_FORM],
+ resource_type=DatasetBase.__name__,
+ )
+
+
+def downgrade():
+ bind = op.get_bind()
+ session = orm.Session(bind=bind)
+ all_environments = session.query(Environment).all()
+ for env in all_environments:
+ policies = ResourcePolicyService.find_resource_policies(
+ session=session,
+ group=env.SamlGroupName,
+ resource_uri=env.environmentUri,
+ resource_type=Environment.__name__,
+ permissions=[ATTACH_METADATA_FORM, CREATE_METADATA_FORM],
+ )
+ for policy in policies:
+ for resource_pol_permission in policy.permissions:
+ if resource_pol_permission.permission.name in [ATTACH_METADATA_FORM, CREATE_METADATA_FORM]:
+ session.delete(resource_pol_permission)
+ session.commit()
+
+ all_organizations = session.query(Organization).all()
+ for org in all_organizations:
+ policies = ResourcePolicyService.find_resource_policies(
+ session=session,
+ group=org.SamlGroupName,
+ resource_uri=org.organizationUri,
+ permissions=[ATTACH_METADATA_FORM, CREATE_METADATA_FORM],
+ resource_type=Organization.__name__,
+ )
+ for policy in policies:
+ for resource_pol_permission in policy.permissions:
+ if resource_pol_permission.permission.name in [ATTACH_METADATA_FORM, CREATE_METADATA_FORM]:
+ session.delete(resource_pol_permission)
+ session.commit()
+
+ datasets = session.query(DatasetBase).all()
+ for dataset in datasets:
+ policies = ResourcePolicyService.find_resource_policies(
+ session=session,
+ group=dataset.SamlAdminGroupName,
+ resource_uri=dataset.datasetUri,
+ permissions=[ATTACH_METADATA_FORM],
+ resource_type=DatasetBase.__name__,
+ )
+
+ for policy in policies:
+ for resource_pol_permission in policy.permissions:
+ if resource_pol_permission.permission.name in [ATTACH_METADATA_FORM, CREATE_METADATA_FORM]:
+ session.delete(resource_pol_permission)
+ session.commit()
diff --git a/backend/migrations/versions/852cdf6cf1e0_add_redshift_datasets.py b/backend/migrations/versions/852cdf6cf1e0_add_redshift_datasets.py
index 3e7a38c35..422d1ffbb 100644
--- a/backend/migrations/versions/852cdf6cf1e0_add_redshift_datasets.py
+++ b/backend/migrations/versions/852cdf6cf1e0_add_redshift_datasets.py
@@ -146,6 +146,7 @@ def downgrade():
permissions=ENVIRONMENT_REDSHIFT_ALL,
)
for policy in policies:
- for permission in policy.permissions:
- session.delete(permission)
- session.commit()
+ for resource_pol_permission in policy.permissions:
+ if resource_pol_permission.permission.name in ENVIRONMENT_REDSHIFT_ALL:
+ session.delete(resource_pol_permission)
+ session.commit()
diff --git a/backend/migrations/versions/f87aecc36d39_attached_field_type_enum.py b/backend/migrations/versions/f87aecc36d39_attached_field_type_enum.py
index 391b52f21..68ab75285 100644
--- a/backend/migrations/versions/f87aecc36d39_attached_field_type_enum.py
+++ b/backend/migrations/versions/f87aecc36d39_attached_field_type_enum.py
@@ -118,8 +118,8 @@ def upgrade():
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
- op.execute('DROP TYPE metadataformfieldtype')
op.alter_column('attached_metadata_form_field', 'type', type_=sa.VARCHAR(), existing_nullable=True)
+ op.execute('DROP TYPE metadataformfieldtype CASCADE')
# ### end Alembic commands ###
# ### commands auto generated by Alembic - please adjust! ###
diff --git a/frontend/src/modules/Environments/views/EnvironmentView.js b/frontend/src/modules/Environments/views/EnvironmentView.js
index 790d97f57..de5d91ee1 100644
--- a/frontend/src/modules/Environments/views/EnvironmentView.js
+++ b/frontend/src/modules/Environments/views/EnvironmentView.js
@@ -275,7 +275,6 @@ const EnvironmentView = () => {
)}
{currentTab === 'teams' && }
diff --git a/frontend/src/modules/Metadata_Forms/components/metadataAttachment.js b/frontend/src/modules/Metadata_Forms/components/metadataAttachment.js
index e29f78675..1ac206290 100644
--- a/frontend/src/modules/Metadata_Forms/components/metadataAttachment.js
+++ b/frontend/src/modules/Metadata_Forms/components/metadataAttachment.js
@@ -16,6 +16,7 @@ import {
import {
deleteAttachedMetadataForm,
getAttachedMetadataForm,
+ getEntityMetadataFormPermissions,
getMetadataForm,
listAttachedMetadataForms,
listEntityMetadataForms
@@ -30,7 +31,7 @@ import DoNotDisturbAltOutlinedIcon from '@mui/icons-material/DoNotDisturbAltOutl
import DeleteIcon from '@mui/icons-material/DeleteOutlined';
export const MetadataAttachment = (props) => {
- const { entityType, entityUri, canEdit } = props;
+ const { entityType, entityUri } = props;
const client = useClient();
const dispatch = useDispatch();
const [selectedForm, setSelectedForm] = useState(null);
@@ -38,6 +39,7 @@ export const MetadataAttachment = (props) => {
const [loadingFields, setLoadingFields] = useState(false);
const [formsList, setFormsList] = useState([]);
const [fields, setFields] = useState([]);
+ const [canEdit, setCanEdit] = useState(false);
const [filter] = useState({
...Defaults.filter,
entityType: entityType,
@@ -139,9 +141,25 @@ export const MetadataAttachment = (props) => {
}
};
+ const getPermissions = async () => {
+ const response = await client.query(
+ getEntityMetadataFormPermissions(entityUri)
+ );
+ if (!response.errors) {
+ setCanEdit(
+ response.data.getEntityMetadataFormPermissions.includes(
+ 'ATTACH_METADATA_FORM'
+ )
+ );
+ }
+ };
+
useEffect(() => {
if (client) {
fetchList().catch((e) => dispatch({ type: SET_ERROR, error: e.message }));
+ getPermissions().catch((e) =>
+ dispatch({ type: SET_ERROR, error: e.message })
+ );
fetchAvailableForms().catch((e) =>
dispatch({ type: SET_ERROR, error: e.message })
);
diff --git a/frontend/src/modules/Metadata_Forms/services/getMetadataFormEntityPermissions.js b/frontend/src/modules/Metadata_Forms/services/getMetadataFormEntityPermissions.js
new file mode 100644
index 000000000..ca268874b
--- /dev/null
+++ b/frontend/src/modules/Metadata_Forms/services/getMetadataFormEntityPermissions.js
@@ -0,0 +1,12 @@
+import { gql } from 'apollo-boost';
+
+export const getEntityMetadataFormPermissions = (entityUri) => ({
+ variables: {
+ entityUri
+ },
+ query: gql`
+ query getEntityMetadataFormPermissions($entityUri: String!) {
+ getEntityMetadataFormPermissions(entityUri: $entityUri)
+ }
+ `
+});
diff --git a/frontend/src/modules/Metadata_Forms/services/index.js b/frontend/src/modules/Metadata_Forms/services/index.js
index 99e3b2312..74c383379 100644
--- a/frontend/src/modules/Metadata_Forms/services/index.js
+++ b/frontend/src/modules/Metadata_Forms/services/index.js
@@ -8,3 +8,4 @@ export * from './attachMetadataForm';
export * from './getAttachedMetadataForm';
export * from './listAttachedMetadataForms';
export * from './deleteAttachedMetadataForm';
+export * from './getMetadataFormEntityPermissions';
diff --git a/frontend/src/modules/Organizations/views/OrganizationView.js b/frontend/src/modules/Organizations/views/OrganizationView.js
index ccc868a39..758409c46 100644
--- a/frontend/src/modules/Organizations/views/OrganizationView.js
+++ b/frontend/src/modules/Organizations/views/OrganizationView.js
@@ -237,7 +237,6 @@ const OrganizationView = () => {
)}
diff --git a/frontend/src/modules/S3_Datasets/views/DatasetView.js b/frontend/src/modules/S3_Datasets/views/DatasetView.js
index 6f1800a64..f47b376c1 100644
--- a/frontend/src/modules/S3_Datasets/views/DatasetView.js
+++ b/frontend/src/modules/S3_Datasets/views/DatasetView.js
@@ -362,11 +362,7 @@ const DatasetView = () => {
)}
{currentTab === 'metadata' && (
-
+
)}
{currentTab === 'overview' && (