diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/Entity.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/Entity.java index 0f13fa2e3ee..28a29576f39 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/Entity.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/Entity.java @@ -51,6 +51,9 @@ public final class Entity { // Canonical entity name to corresponding EntityRepository map private static final Map> ENTITY_REPOSITORY_MAP = new HashMap<>(); + // List of entities + private static final List ENTITY_LIST = new ArrayList<>(); + // Common field names public static final String FIELD_OWNER = "owner"; public static final String FIELD_NAME = "name"; @@ -138,6 +141,9 @@ public final class Entity { DAO_MAP.put(entity, dao); ENTITY_REPOSITORY_MAP.put(entity, entityRepository); CANONICAL_ENTITY_NAME_MAP.put(entity.toLowerCase(Locale.ROOT), entity); + ENTITY_LIST.add(entity); + Collections.sort(ENTITY_LIST); + LOG.info( "Registering entity {} {} {} {}", clazz, @@ -146,6 +152,10 @@ public final class Entity { entityRepository.getClass().getSimpleName()); } + public static List listEntities() { + return Collections.unmodifiableList(ENTITY_LIST); + } + public static EntityReference getEntityReference(EntityReference ref) throws IOException { return ref == null ? null : getEntityReferenceById(ref.getType(), ref.getId(), Include.NON_DELETED); } diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java index 09a26c0e066..c44c0c55730 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java @@ -31,7 +31,6 @@ import org.openmetadata.catalog.entity.data.Location; import org.openmetadata.catalog.entity.policies.Policy; import org.openmetadata.catalog.entity.policies.accessControl.Rule; import org.openmetadata.catalog.exception.CatalogExceptionMessage; -import org.openmetadata.catalog.jdbi3.EntityRepository.EntityUpdater; import org.openmetadata.catalog.resources.policies.PolicyResource; import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.MetadataOperation; @@ -142,10 +141,8 @@ public class PolicyRepository extends EntityRepository { LOG.debug("Validating rules for {} policy: {}", PolicyType.AccessControl, policy.getName()); Set operations = new HashSet<>(); - for (Object ruleObject : policy.getRules()) { - // Cast to access control policy Rule. - Rule rule = JsonUtils.readValue(JsonUtils.getJsonStructure(ruleObject).toString(), Rule.class); - + List rules = EntityUtil.resolveRules(policy.getRules()); + for (Rule rule : rules) { if (rule.getOperation() == null) { throw new IllegalArgumentException( CatalogExceptionMessage.invalidPolicyOperationNull(rule.getName(), policy.getName())); @@ -192,7 +189,6 @@ public class PolicyRepository extends EntityRepository { if (original.getPolicyType() != updated.getPolicyType()) { throw new IllegalArgumentException(CatalogExceptionMessage.readOnlyAttribute(POLICY, "policyType")); } - recordChange("policyUrl", original.getPolicyUrl(), updated.getPolicyUrl()); recordChange(ENABLED, original.getEnabled(), updated.getEnabled()); recordChange("rules", original.getRules(), updated.getRules()); updateLocation(original, updated); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/lineage/LineageResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/lineage/LineageResource.java index 9b4c9cd9eaf..47a18560714 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/lineage/LineageResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/lineage/LineageResource.java @@ -165,7 +165,7 @@ public class LineageResource { public Response addLineage( @Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid AddLineage addLineage) throws IOException { - SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, null, MetadataOperation.UpdateLineage); + SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, null, MetadataOperation.EDIT_LINEAGE); dao.addLineage(addLineage); return Response.status(Status.OK).build(); } @@ -201,7 +201,7 @@ public class LineageResource { @Parameter(description = "Entity id", required = true, schema = @Schema(type = "string")) @PathParam("toId") String toId) throws IOException { - SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, null, MetadataOperation.UpdateLineage); + SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, null, MetadataOperation.EDIT_LINEAGE); boolean deleted = dao.deleteLineage(fromEntity, fromId, toEntity, toId); if (!deleted) { diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/policies/PolicyResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/policies/PolicyResource.java index 51062a9572d..0adc4641860 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/policies/PolicyResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/policies/PolicyResource.java @@ -27,6 +27,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.json.JsonPatch; import javax.validation.Valid; @@ -48,6 +50,7 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; import javax.ws.rs.core.UriInfo; +import lombok.extern.slf4j.Slf4j; import org.openmetadata.catalog.CatalogApplicationConfig; import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.api.policies.CreatePolicy; @@ -62,8 +65,10 @@ import org.openmetadata.catalog.security.policyevaluator.PolicyEvaluator; import org.openmetadata.catalog.type.EntityHistory; import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.Include; +import org.openmetadata.catalog.type.MetadataOperation; import org.openmetadata.catalog.util.ResultList; +@Slf4j @Path("/v1/policies") @Api(value = "Policies collection", tags = "Policies collection") @Produces(MediaType.APPLICATION_JSON) @@ -71,6 +76,7 @@ import org.openmetadata.catalog.util.ResultList; @Collection(name = "policies") public class PolicyResource extends EntityResource { public static final String COLLECTION_PATH = "v1/policies/"; + public static final List RESOURCES = new ArrayList<>(); @Override public Policy addHref(UriInfo uriInfo, Policy policy) { @@ -87,6 +93,7 @@ public class PolicyResource extends EntityResource { // Set up the PolicyEvaluator, before loading seed data. PolicyEvaluator policyEvaluator = PolicyEvaluator.getInstance(); policyEvaluator.setPolicyRepository(dao); + // Load any existing rules from database, before loading seed data. policyEvaluator.load(); dao.initSeedDataFromResources(); @@ -103,6 +110,17 @@ public class PolicyResource extends EntityResource { } } + public static class OperationList extends ResultList { + @SuppressWarnings("unused") + OperationList() { + // Empty constructor needed for deserialization + } + + public OperationList(List data, String beforeCursor, String afterCursor, int total) { + super(data, beforeCursor, afterCursor, total); + } + } + public static final String FIELDS = "owner,location"; @GET @@ -268,6 +286,30 @@ public class PolicyResource extends EntityResource { return dao.getVersion(id, version); } + @GET + @Path("/resources") + @Operation( + operationId = "listPolicyResources", + summary = "Get list of policy resources used in authoring a policy.", + tags = "policies", + description = "Get all the resources used in policy authoring", + responses = { + @ApiResponse(responseCode = "200", description = "policy", content = @Content(mediaType = "application/json")), + @ApiResponse( + responseCode = "404", + description = "Policy for instance {id} and version {version} is" + " " + "not found") + }) + public List listPolicyResources(@Context UriInfo uriInfo, @Context SecurityContext securityContext) + throws IOException { + if (RESOURCES.isEmpty()) { + // Load set of resource types + RESOURCES.addAll(Entity.listEntities()); + RESOURCES.add("lineage"); + Collections.sort(RESOURCES); + } + return RESOURCES; + } + @POST @Operation( operationId = "createPolicy", @@ -367,7 +409,6 @@ public class PolicyResource extends EntityResource { private Policy getPolicy(CreatePolicy create, String user) { Policy policy = copy(new Policy(), create, user) - .withPolicyUrl(create.getPolicyUrl()) .withPolicyType(create.getPolicyType()) .withRules(create.getRules()) .withEnabled(create.getEnabled()); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/RoleResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/RoleResource.java index c27df6bad92..4f78dad7554 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/RoleResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/RoleResource.java @@ -75,7 +75,7 @@ import org.openmetadata.catalog.util.ResultList; @Api(value = "Roles collection", tags = "Roles collection") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) -@Collection(name = "roles", order = 1) // Load after PolicyResource at Order 0 +@Collection(name = "roles", order = 2) // Load after PolicyResource at Order 0 // policies exist before // loading roles @Slf4j diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java index f348202df36..d54f09167d9 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java @@ -40,6 +40,7 @@ import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.api.data.TermReference; import org.openmetadata.catalog.entity.data.GlossaryTerm; import org.openmetadata.catalog.entity.data.Table; +import org.openmetadata.catalog.entity.policies.accessControl.Rule; import org.openmetadata.catalog.entity.type.CustomProperty; import org.openmetadata.catalog.exception.CatalogExceptionMessage; import org.openmetadata.catalog.exception.EntityNotFoundException; @@ -352,4 +353,13 @@ public final class EntityUtil { .withFullyQualifiedName(from.getFullyQualifiedName()) .withDeleted(from.getDeleted()); } + + public static List resolveRules(List rules) throws IOException { + List resolvedRules = new ArrayList<>(); + for (Object ruleObject : rules) { + // Cast to access control policy Rule. + resolvedRules.add(JsonUtils.readValue(JsonUtils.getJsonStructure(ruleObject).toString(), Rule.class)); + } + return resolvedRules; + } } diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/JsonPatchUtils.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/JsonPatchUtils.java index aa438a198dc..c488a90b8f5 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/JsonPatchUtils.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/JsonPatchUtils.java @@ -25,16 +25,16 @@ public class JsonPatchUtils { String path = jsonPatchMap.get("path").toString(); if (path.contains(FIELD_DESCRIPTION)) { - return MetadataOperation.UpdateDescription; + return MetadataOperation.EDIT_DESCRIPTION; } if (path.contains("tags")) { - return MetadataOperation.UpdateTags; + return MetadataOperation.EDIT_TAGS; } if (path.contains(FIELD_OWNER)) { - return MetadataOperation.UpdateOwner; + return MetadataOperation.EDIT_OWNER; } if (path.startsWith("/users")) { // Ability to update users within a team. - return MetadataOperation.UpdateTeam; + return MetadataOperation.TEAM_EDIT_USERS; } return null; } diff --git a/catalog-rest-service/src/main/resources/json/data/policy/DataConsumerPolicy.json b/catalog-rest-service/src/main/resources/json/data/policy/DataConsumerPolicy.json index 0fe4b2124e2..938913a02a5 100644 --- a/catalog-rest-service/src/main/resources/json/data/policy/DataConsumerPolicy.json +++ b/catalog-rest-service/src/main/resources/json/data/policy/DataConsumerPolicy.json @@ -7,20 +7,20 @@ "enabled": true, "rules": [ { - "name": "DataConsumerPolicy-UpdateDescription", - "operation": "UpdateDescription", + "name": "DataConsumerPolicy-editDescription", + "operation": "EditDescription", "allow": true, "priority": 1000 }, { - "name": "DataConsumerPolicy-UpdateOwner", - "operation": "UpdateOwner", + "name": "DataConsumerPolicy-editOwner", + "operation": "EditOwner", "allow": true, "priority": 1000 }, { - "name": "DataConsumerPolicy-UpdateTags", - "operation": "UpdateTags", + "name": "DataConsumerPolicy-editTags", + "operation": "EditTags", "allow": true, "priority": 1000 } diff --git a/catalog-rest-service/src/main/resources/json/data/policy/DataStewardPolicy.json b/catalog-rest-service/src/main/resources/json/data/policy/DataStewardPolicy.json index 11ea56056a9..5fcd8024457 100644 --- a/catalog-rest-service/src/main/resources/json/data/policy/DataStewardPolicy.json +++ b/catalog-rest-service/src/main/resources/json/data/policy/DataStewardPolicy.json @@ -5,29 +5,28 @@ "description": "Policy for Data Steward Role to perform operations on metadata entities", "policyType": "AccessControl", "enabled": true, - "deleted": false, "rules": [ { - "name": "DataStewardPolicy-UpdateDescription", - "operation": "UpdateDescription", + "name": "DataStewardPolicy-editDescription", + "operation": "EditDescription", "allow": true, "priority": 1000 }, { - "name": "DataStewardPolicy-UpdateLineage", - "operation": "UpdateLineage", + "name": "DataStewardPolicy-editLineage", + "operation": "EditLineage", "allow": true, "priority": 1000 }, { - "name": "DataStewardPolicy-UpdateOwner", - "operation": "UpdateOwner", + "name": "DataStewardPolicy-editOwner", + "operation": "EditOwner", "allow": true, "priority": 1000 }, { - "name": "DataStewardPolicy-UpdateTags", - "operation": "UpdateTags", + "name": "DataStewardPolicy-editTags", + "operation": "EditTags", "allow": true, "priority": 1000 } diff --git a/catalog-rest-service/src/main/resources/json/schema/api/policies/createPolicy.json b/catalog-rest-service/src/main/resources/json/schema/api/policies/createPolicy.json index 8dabdcb9b7d..35fcf9c2dda 100644 --- a/catalog-rest-service/src/main/resources/json/schema/api/policies/createPolicy.json +++ b/catalog-rest-service/src/main/resources/json/schema/api/policies/createPolicy.json @@ -24,11 +24,6 @@ "description": "Owner of this Policy.", "$ref": "../../type/entityReference.json" }, - "policyUrl": { - "description": "Link to a well documented definition of this Policy.", - "type": "string", - "format": "uri" - }, "policyType": { "$ref": "../../entity/policies/policy.json#/definitions/policyType" }, diff --git a/catalog-rest-service/src/main/resources/json/schema/entity/policies/accessControl/rule.json b/catalog-rest-service/src/main/resources/json/schema/entity/policies/accessControl/rule.json index 6252470d5e2..dd9c5c06eef 100644 --- a/catalog-rest-service/src/main/resources/json/schema/entity/policies/accessControl/rule.json +++ b/catalog-rest-service/src/main/resources/json/schema/entity/policies/accessControl/rule.json @@ -11,24 +11,27 @@ "description": "This schema defines all possible operations on metadata of data entities.", "type": "string", "enum": [ - "SuggestDescription", - "SuggestTags", - "UpdateDescription", - "UpdateOwner", - "UpdateTags", - "UpdateLineage", - "DecryptTokens", - "UpdateTeam" - ], - "javaEnums": [ - { "name": "SuggestDescription" }, - { "name": "SuggestTags" }, - { "name": "UpdateDescription" }, - { "name": "UpdateOwner" }, - { "name": "UpdateTags" }, - { "name": "UpdateLineage" }, - { "name": "DecryptTokens" }, - { "name": "UpdateTeam" } + "Create", + "Delete", + "ViewAll", + "ViewUsage", + "ViewTests", + "TableViewQueries", + "TableViewDataProfile", + "TableViewSampleData", + "EditAll", + "EditDescription", + "EditTags", + "EditOwner", + "EditTier", + "EditCustomFields", + "EditLineage", + "EditReviewers", + "EditTests", + "TableEditQueries", + "TableEditDataProfile", + "TableEditSampleData", + "TeamEditUsers" ] } }, @@ -72,6 +75,8 @@ "default": false } }, - "required": ["name"], + "required": [ + "name" + ], "additionalProperties": false } diff --git a/catalog-rest-service/src/main/resources/json/schema/entity/policies/policy.json b/catalog-rest-service/src/main/resources/json/schema/entity/policies/policy.json index 73c49c87087..c085b608f27 100644 --- a/catalog-rest-service/src/main/resources/json/schema/entity/policies/policy.json +++ b/catalog-rest-service/src/main/resources/json/schema/entity/policies/policy.json @@ -62,12 +62,6 @@ "$ref": "../../type/entityReference.json", "default": null }, - "policyUrl": { - "description": "Link to a well documented definition of this Policy.", - "type": "string", - "format": "uri", - "default": null - }, "href": { "description": "Link to the resource corresponding to this entity.", "$ref": "../../type/basic.json#/definitions/href" @@ -97,7 +91,7 @@ "$ref": "../../type/entityHistory.json#/definitions/changeDescription" }, "rules": { - "description": "Rules that the policy has.", + "description": "Set of rules that the policy contains.", "$ref": "#/definitions/rules" }, "location": { diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java index fb2f3d0b4ef..37db4e8c4dc 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java @@ -1576,7 +1576,7 @@ public abstract class EntityResourceTest patchEntity(entity.getId(), originalJson, entity, authHeaders(userName + "@open-metadata.org")), FORBIDDEN, - noPermission(userName, "UpdateDescription")); + noPermission(userName, "editDescription")); // Revert to original. entity.setDescription(originalDescription); return entity; diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/lineage/LineageResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/lineage/LineageResourceTest.java index 4b90aa26775..105655e2334 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/lineage/LineageResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/lineage/LineageResourceTest.java @@ -114,11 +114,11 @@ public class LineageResourceTest extends CatalogApplicationTest { assertResponse( () -> addEdge(TABLES.get(1), TABLES.get(2), null, authHeaders), FORBIDDEN, - noPermission(userName, "UpdateLineage")); + noPermission(userName, "EditLineage")); assertResponse( () -> deleteEdge(TABLES.get(1), TABLES.get(2), authHeaders), FORBIDDEN, - noPermission(userName, "UpdateLineage")); + noPermission(userName, "EditLineage")); return; } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/permissions/PermissionsResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/permissions/PermissionsResourceTest.java index d9949b03318..cc428b7973f 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/permissions/PermissionsResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/permissions/PermissionsResourceTest.java @@ -80,48 +80,32 @@ class PermissionsResourceTest extends CatalogApplicationTest { } private Stream getPermissionsTestParams() { + HashMap adminPermissions = new HashMap<>(); + HashMap dataStewardPermissions = new HashMap<>(); + HashMap dataConsumerPermissions = new HashMap<>(); + for (MetadataOperation op : MetadataOperation.values()) { + adminPermissions.put(op, Boolean.TRUE); + dataStewardPermissions.put(op, Boolean.FALSE); + dataConsumerPermissions.put(op, Boolean.FALSE); + } + + dataStewardPermissions.put(MetadataOperation.EDIT_DESCRIPTION, Boolean.TRUE); + dataStewardPermissions.put(MetadataOperation.EDIT_LINEAGE, Boolean.TRUE); + dataStewardPermissions.put(MetadataOperation.EDIT_OWNER, Boolean.TRUE); + dataStewardPermissions.put(MetadataOperation.EDIT_TAGS, Boolean.TRUE); + // put(MetadataOperation.DecryptTokens, Boolean.FALSE); + dataStewardPermissions.put(MetadataOperation.TEAM_EDIT_USERS, Boolean.FALSE); + + dataConsumerPermissions.put(MetadataOperation.EDIT_DESCRIPTION, Boolean.TRUE); + dataConsumerPermissions.put(MetadataOperation.EDIT_LINEAGE, Boolean.FALSE); + dataConsumerPermissions.put(MetadataOperation.EDIT_OWNER, Boolean.TRUE); + dataConsumerPermissions.put(MetadataOperation.EDIT_TAGS, Boolean.TRUE); + // put(MetadataOperation.DecryptTokens, Boolean.FALSE); + dataConsumerPermissions.put(MetadataOperation.TEAM_EDIT_USERS, Boolean.FALSE); + return Stream.of( - Arguments.of( - TestUtils.ADMIN_USER_NAME, - new HashMap() { - { - put(MetadataOperation.SuggestDescription, Boolean.TRUE); - put(MetadataOperation.SuggestTags, Boolean.TRUE); - put(MetadataOperation.UpdateDescription, Boolean.TRUE); - put(MetadataOperation.UpdateLineage, Boolean.TRUE); - put(MetadataOperation.UpdateOwner, Boolean.TRUE); - put(MetadataOperation.UpdateTags, Boolean.TRUE); - put(MetadataOperation.DecryptTokens, Boolean.TRUE); - put(MetadataOperation.UpdateTeam, Boolean.TRUE); - } - }), - Arguments.of( - DATA_STEWARD_USER_NAME, - new HashMap() { - { - put(MetadataOperation.UpdateDescription, Boolean.TRUE); - put(MetadataOperation.UpdateLineage, Boolean.TRUE); - put(MetadataOperation.UpdateOwner, Boolean.TRUE); - put(MetadataOperation.UpdateTags, Boolean.TRUE); - put(MetadataOperation.SuggestDescription, Boolean.FALSE); - put(MetadataOperation.SuggestTags, Boolean.FALSE); - put(MetadataOperation.DecryptTokens, Boolean.FALSE); - put(MetadataOperation.UpdateTeam, Boolean.FALSE); - } - }), - Arguments.of( - DATA_CONSUMER_USER_NAME, - new HashMap() { - { - put(MetadataOperation.SuggestDescription, Boolean.FALSE); - put(MetadataOperation.SuggestTags, Boolean.FALSE); - put(MetadataOperation.UpdateDescription, Boolean.TRUE); - put(MetadataOperation.UpdateLineage, Boolean.FALSE); - put(MetadataOperation.UpdateOwner, Boolean.TRUE); - put(MetadataOperation.UpdateTags, Boolean.TRUE); - put(MetadataOperation.DecryptTokens, Boolean.FALSE); - put(MetadataOperation.UpdateTeam, Boolean.FALSE); - } - })); + Arguments.of(TestUtils.ADMIN_USER_NAME, adminPermissions), + Arguments.of(DATA_STEWARD_USER_NAME, dataStewardPermissions), + Arguments.of(DATA_CONSUMER_USER_NAME, dataConsumerPermissions)); } } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/policies/PolicyResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/policies/PolicyResourceTest.java index f25169d535b..2e385d8c3a5 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/policies/PolicyResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/policies/PolicyResourceTest.java @@ -15,7 +15,7 @@ package org.openmetadata.catalog.resources.policies; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.openmetadata.catalog.util.TestUtils.ADMIN_AUTH_HEADERS; import static org.openmetadata.catalog.util.TestUtils.UpdateType.MINOR_UPDATE; import static org.openmetadata.catalog.util.TestUtils.assertListNotNull; @@ -30,6 +30,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import javax.ws.rs.client.WebTarget; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.http.client.HttpResponseException; import org.junit.jupiter.api.BeforeAll; @@ -50,6 +52,7 @@ import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.FieldChange; import org.openmetadata.catalog.type.MetadataOperation; import org.openmetadata.catalog.type.PolicyType; +import org.openmetadata.catalog.util.EntityUtil; import org.openmetadata.catalog.util.JsonUtils; import org.openmetadata.catalog.util.PolicyUtils; import org.openmetadata.catalog.util.TestUtils; @@ -77,8 +80,13 @@ public class PolicyResourceTest extends EntityResourceTest } @Override + @SneakyThrows public void validateCreatedEntity(Policy policy, CreatePolicy createRequest, Map authHeaders) { - assertEquals(createRequest.getPolicyUrl(), policy.getPolicyUrl()); + assertEquals(createRequest.getPolicyType(), policy.getPolicyType()); + if (createRequest.getLocation() != null) { + assertEquals(createRequest.getLocation(), policy.getLocation().getId()); + } + assertEquals(createRequest.getRules(), EntityUtil.resolveRules(policy.getRules())); } @Override @@ -120,8 +128,8 @@ public class PolicyResourceTest extends EntityResourceTest @Test void post_AccessControlPolicyWithValidRules_200_ok(TestInfo test) throws IOException { List rules = new ArrayList<>(); - rules.add(PolicyUtils.accessControlRule(null, null, MetadataOperation.UpdateDescription, true, 0)); - rules.add(PolicyUtils.accessControlRule(null, null, "DataConsumer", MetadataOperation.UpdateTags, true, 1)); + rules.add(PolicyUtils.accessControlRule(null, null, MetadataOperation.EDIT_DESCRIPTION, true, 0)); + rules.add(PolicyUtils.accessControlRule(null, null, "DataConsumer", MetadataOperation.EDIT_TAGS, true, 1)); CreatePolicy create = createAccessControlPolicyWithRules(getEntityName(test), rules); createAndCheckEntity(create, ADMIN_AUTH_HEADERS); } @@ -143,46 +151,31 @@ public class PolicyResourceTest extends EntityResourceTest @Test void post_AccessControlPolicyWithDuplicateRules_400_error(TestInfo test) { List rules = new ArrayList<>(); - rules.add(PolicyUtils.accessControlRule("rule1", null, null, MetadataOperation.UpdateDescription, true, 0)); - rules.add(PolicyUtils.accessControlRule("rule2", null, null, MetadataOperation.UpdateTags, true, 1)); - rules.add(PolicyUtils.accessControlRule("rule3", null, null, MetadataOperation.UpdateTags, true, 1)); - CreatePolicy create = createAccessControlPolicyWithRules(getEntityName(test), rules); + rules.add(PolicyUtils.accessControlRule("rule1", null, null, MetadataOperation.EDIT_DESCRIPTION, true, 0)); + rules.add(PolicyUtils.accessControlRule("rule2", null, null, MetadataOperation.EDIT_TAGS, true, 1)); + rules.add(PolicyUtils.accessControlRule("rule3", null, null, MetadataOperation.EDIT_TAGS, true, 1)); + String policyName = getEntityName(test); + CreatePolicy create = createAccessControlPolicyWithRules(policyName, rules); assertResponseContains( () -> createEntity(create, ADMIN_AUTH_HEADERS), BAD_REQUEST, String.format( - "Found multiple rules with operation UpdateTags within policy %s. " + "Found multiple rules with operation EditTags within policy %s. " + "Please ensure that operation across all rules within the policy are distinct", - getEntityName(test))); + policyName)); } @Test void patch_PolicyAttributes_200_ok(TestInfo test) throws IOException { Policy policy = createAndCheckEntity(createRequest(test), ADMIN_AUTH_HEADERS).withLocation(null); - URI uri = null; - try { - uri = new URI("http://www.example.com/policy1"); - } catch (URISyntaxException e) { - fail("could not construct URI for test"); - } - - // Add policyUrl which was previously null and set enabled to false + // Set enabled to false String origJson = JsonUtils.pojoToJson(policy); - policy.setPolicyUrl(uri); policy.setEnabled(false); ChangeDescription change = getChangeDescription(policy.getVersion()); - change.getFieldsAdded().add(new FieldChange().withName("policyUrl").withNewValue(uri)); change.getFieldsUpdated().add(new FieldChange().withName("enabled").withOldValue(true).withNewValue(false)); policy = patchEntityAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); - // Remove policyUrl - origJson = JsonUtils.pojoToJson(policy); - policy.setPolicyUrl(null); - change = getChangeDescription(policy.getVersion()); - change.getFieldsDeleted().add(new FieldChange().withName("policyUrl").withOldValue(uri)); - policy = patchEntityAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); - EntityReference locationReference = location.getEntityReference(); // Add new field location @@ -193,6 +186,15 @@ public class PolicyResourceTest extends EntityResourceTest patchEntityAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); } + @Test + public void get_policyResources() throws HttpResponseException { + // Get list of policy resources and make sure it has all the entities and other resources + List resources = getPolicyResources(ADMIN_AUTH_HEADERS); + List entities = Entity.listEntities(); + assertTrue(resources.containsAll(entities)); + assertTrue(resources.contains("lineage")); + } + @Override public Policy validateGetWithDifferentFields(Policy policy, boolean byName) throws HttpResponseException { String fields = ""; @@ -228,4 +230,9 @@ public class PolicyResourceTest extends EntityResourceTest CreateLocation createLocation = locationResourceTest.createRequest(LOCATION_NAME, "", "", null); return TestUtils.post(getResource("locations"), createLocation, Location.class, ADMIN_AUTH_HEADERS); } + + public final List getPolicyResources(Map authHeaders) throws HttpResponseException { + WebTarget target = getResource(collectionName + "/resources"); + return (List) TestUtils.get(target, List.class, authHeaders); + } } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/TeamResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/TeamResourceTest.java index 1d8dc8bc6ff..fdc76bddd75 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/TeamResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/TeamResourceTest.java @@ -190,7 +190,7 @@ public class TeamResourceTest extends EntityResourceTest { patchEntity( team.getId(), originalJson, team, SecurityUtil.authHeaders(randomUserName + "@open-metadata.org")), FORBIDDEN, - CatalogExceptionMessage.noPermission(randomUserName, "UpdateTeam")); + CatalogExceptionMessage.noPermission(randomUserName, "TeamEditUsers")); // Ensure user with UpdateTeam permission can add users to a team. User teamManagerUser = createTeamManager(test); @@ -208,7 +208,10 @@ public class TeamResourceTest extends EntityResourceTest { private User createTeamManager(TestInfo testInfo) throws HttpResponseException { // Create a rule that can update team Rule rule = - new Rule().withName("TeamManagerPolicy-UpdateTeam").withAllow(true).withOperation(MetadataOperation.UpdateTeam); + new Rule() + .withName("TeamManagerPolicy-UpdateTeam") + .withAllow(true) + .withOperation(MetadataOperation.TEAM_EDIT_USERS); // Create a policy with the rule PolicyResourceTest policyResourceTest = new PolicyResourceTest(); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DashboardDetails/DashboardDetails.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DashboardDetails/DashboardDetails.component.tsx index 493f8457246..af8324af3f0 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DashboardDetails/DashboardDetails.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DashboardDetails/DashboardDetails.component.tsx @@ -589,7 +589,7 @@ const DashboardDetails = ({ Boolean(owner) )} isOwner={hasEditAccess()} - permission={Operation.UpdateDescription} + permission={Operation.EditDescription} position="top">