mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-18 14:06:59 +00:00
#16279 Update Classification Schema to include Governance Fields - Schema and Java Implementation (#21636)
* Update Classification Schema to include Governance Fields * Removed Tags, Reviewers, Domain from Classification as they are needed and corrected tests * Added Permission check for owners in Classification Resource Test * Added LoadTags.ts generated from createClassificationSchema.json * Only have my schema changes in the typescript files, ignore other changes. --------- Co-authored-by: Mohit Yadav <105265192+mohityadav766@users.noreply.github.com>
This commit is contained in:
parent
b8cb82c25c
commit
febd195bfd
@ -79,7 +79,7 @@ public class ClassificationResource
|
||||
extends EntityResource<Classification, ClassificationRepository> {
|
||||
private final ClassificationMapper mapper = new ClassificationMapper();
|
||||
public static final String TAG_COLLECTION_PATH = "/v1/classifications/";
|
||||
static final String FIELDS = "usageCount,termCount";
|
||||
static final String FIELDS = "owners,usageCount,termCount";
|
||||
|
||||
static class ClassificationList extends ResultList<Classification> {
|
||||
/* Required for serde */
|
||||
|
@ -14,9 +14,14 @@
|
||||
package org.openmetadata.service.resources.tags;
|
||||
|
||||
import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST;
|
||||
import static jakarta.ws.rs.core.Response.Status.FORBIDDEN;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
|
||||
import static org.openmetadata.service.Entity.FIELD_OWNERS;
|
||||
import static org.openmetadata.service.exception.CatalogExceptionMessage.permissionNotAllowed;
|
||||
import static org.openmetadata.service.security.SecurityUtil.authHeaders;
|
||||
import static org.openmetadata.service.util.EntityUtil.fieldAdded;
|
||||
import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
|
||||
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
|
||||
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
|
||||
@ -40,6 +45,7 @@ import org.openmetadata.schema.api.classification.CreateClassification;
|
||||
import org.openmetadata.schema.entity.classification.Classification;
|
||||
import org.openmetadata.schema.entity.classification.Tag;
|
||||
import org.openmetadata.schema.type.ChangeDescription;
|
||||
import org.openmetadata.schema.type.MetadataOperation;
|
||||
import org.openmetadata.schema.type.ProviderType;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.exception.CatalogExceptionMessage;
|
||||
@ -91,6 +97,54 @@ public class ClassificationResourceTest
|
||||
classification.getName(), Entity.CLASSIFICATION));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_classificationOwnerPermissions(TestInfo test) throws IOException {
|
||||
// Create classification without owners
|
||||
CreateClassification create = createRequest(getEntityName(test));
|
||||
Classification classification = createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
|
||||
assertTrue(
|
||||
listOrEmpty(classification.getOwners()).isEmpty(),
|
||||
"Classification should have no owners initially");
|
||||
|
||||
// Update classification owners as admin using PATCH
|
||||
String json = JsonUtils.pojoToJson(classification);
|
||||
classification.setOwners(List.of(USER1.getEntityReference()));
|
||||
ChangeDescription change = getChangeDescription(classification, MINOR_UPDATE);
|
||||
fieldAdded(change, FIELD_OWNERS, List.of(USER1.getEntityReference()));
|
||||
classification =
|
||||
patchEntityAndCheck(classification, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||
assertEquals(
|
||||
1, listOrEmpty(classification.getOwners()).size(), "Classification should have one owner");
|
||||
assertEquals(
|
||||
USER1.getId(), classification.getOwners().get(0).getId(), "Owner should match USER1");
|
||||
|
||||
// Update owners as USER2 with USER2 credentials (should fail with 403)
|
||||
String originalJson = JsonUtils.pojoToJson(classification);
|
||||
classification.setOwners(List.of(USER2.getEntityReference()));
|
||||
Classification finalClassification = classification;
|
||||
assertResponse(
|
||||
() ->
|
||||
patchEntity(
|
||||
finalClassification.getId(),
|
||||
originalJson,
|
||||
finalClassification,
|
||||
authHeaders(USER2.getName())),
|
||||
FORBIDDEN,
|
||||
permissionNotAllowed(USER2.getName(), List.of(MetadataOperation.EDIT_OWNERS)));
|
||||
|
||||
// Verify the above change did not change the owners, USER1 should still be the owner
|
||||
Classification retrievedClassification =
|
||||
getEntity(classification.getId(), "owners", ADMIN_AUTH_HEADERS);
|
||||
assertEquals(
|
||||
1,
|
||||
listOrEmpty(retrievedClassification.getOwners()).size(),
|
||||
"Classification should still have one owner");
|
||||
assertEquals(
|
||||
USER1.getId(),
|
||||
retrievedClassification.getOwners().get(0).getId(),
|
||||
"Owner should still be USER1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateClassification createRequest(String name) {
|
||||
return new CreateClassification()
|
||||
@ -120,18 +174,20 @@ public class ClassificationResourceTest
|
||||
@Override
|
||||
public Classification validateGetWithDifferentFields(
|
||||
Classification classification, boolean byName) throws HttpResponseException {
|
||||
String fields = "";
|
||||
classification =
|
||||
byName
|
||||
? getEntityByName(classification.getFullyQualifiedName(), null, ADMIN_AUTH_HEADERS)
|
||||
: getEntity(classification.getId(), null, ADMIN_AUTH_HEADERS);
|
||||
assertListNull(classification.getUsageCount());
|
||||
? getEntityByName(classification.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS)
|
||||
: getEntity(classification.getId(), fields, ADMIN_AUTH_HEADERS);
|
||||
assertListNull(classification.getOwners());
|
||||
|
||||
String fields = "usageCount";
|
||||
fields = "owners,usageCount";
|
||||
classification =
|
||||
byName
|
||||
? getEntityByName(classification.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS)
|
||||
: getEntity(classification.getId(), fields, ADMIN_AUTH_HEADERS);
|
||||
assertListNotNull(classification.getUsageCount());
|
||||
assertListNotNull(classification.getOwners());
|
||||
return classification;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,11 @@
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Table belongs to.",
|
||||
"type": "string"
|
||||
},
|
||||
"owners": {
|
||||
"description": "Owners of this classification term.",
|
||||
"$ref": "../../type/entityReferenceList.json",
|
||||
"default": null
|
||||
}
|
||||
},
|
||||
"required": ["name", "description"],
|
||||
|
@ -80,6 +80,10 @@
|
||||
"domain" : {
|
||||
"description": "Domain the asset belongs to. When not set, the asset inherits the domain from the parent it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"owners": {
|
||||
"description": "Owners of this Classification.",
|
||||
"$ref": "../../type/entityReferenceList.json"
|
||||
}
|
||||
},
|
||||
"required": ["name", "description"],
|
||||
|
@ -36,9 +36,69 @@ export interface CreateClassification {
|
||||
*/
|
||||
mutuallyExclusive?: boolean;
|
||||
name: string;
|
||||
/**
|
||||
* Owners of this classification term.
|
||||
*/
|
||||
owners?: EntityReference[];
|
||||
provider?: ProviderType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Owners of this classification term.
|
||||
*
|
||||
* This schema defines the EntityReferenceList type used for referencing an entity.
|
||||
* EntityReference is used for capturing relationships from one entity to another. For
|
||||
* example, a table has an attribute called database of type EntityReference that captures
|
||||
* the relationship of a table `belongs to a` database.
|
||||
*
|
||||
* This schema defines the EntityReference type used for referencing an entity.
|
||||
* EntityReference is used for capturing relationships from one entity to another. For
|
||||
* example, a table has an attribute called database of type EntityReference that captures
|
||||
* the relationship of a table `belongs to a` database.
|
||||
*/
|
||||
export interface EntityReference {
|
||||
/**
|
||||
* If true the entity referred to has been soft-deleted.
|
||||
*/
|
||||
deleted?: boolean;
|
||||
/**
|
||||
* Optional description of entity.
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* Display Name that identifies this entity.
|
||||
*/
|
||||
displayName?: string;
|
||||
/**
|
||||
* Fully qualified name of the entity instance. For entities such as tables, databases
|
||||
* fullyQualifiedName is returned in this field. For entities that don't have name hierarchy
|
||||
* such as `user` and `team` this will be same as the `name` field.
|
||||
*/
|
||||
fullyQualifiedName?: string;
|
||||
/**
|
||||
* Link to the entity resource.
|
||||
*/
|
||||
href?: string;
|
||||
/**
|
||||
* Unique identifier that identifies an entity instance.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* If true the relationship indicated by this entity reference is inherited from the parent
|
||||
* entity.
|
||||
*/
|
||||
inherited?: boolean;
|
||||
/**
|
||||
* Name of the entity instance.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* Entity type/class name - Examples: `database`, `table`, `metrics`, `databaseService`,
|
||||
* `dashboardService`...
|
||||
*/
|
||||
type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of provider of an entity. Some entities are provided by the `system`. Some are
|
||||
* entities created and provided by the `user`. Typically `system` provide entities can't be
|
||||
|
@ -44,9 +44,69 @@ export interface CreateClassificationRequest {
|
||||
*/
|
||||
mutuallyExclusive?: boolean;
|
||||
name: string;
|
||||
/**
|
||||
* Owners of this classification term.
|
||||
*/
|
||||
owners?: EntityReference[];
|
||||
provider?: ProviderType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Owners of this classification term.
|
||||
*
|
||||
* This schema defines the EntityReferenceList type used for referencing an entity.
|
||||
* EntityReference is used for capturing relationships from one entity to another. For
|
||||
* example, a table has an attribute called database of type EntityReference that captures
|
||||
* the relationship of a table `belongs to a` database.
|
||||
*
|
||||
* This schema defines the EntityReference type used for referencing an entity.
|
||||
* EntityReference is used for capturing relationships from one entity to another. For
|
||||
* example, a table has an attribute called database of type EntityReference that captures
|
||||
* the relationship of a table `belongs to a` database.
|
||||
*/
|
||||
export interface EntityReference {
|
||||
/**
|
||||
* If true the entity referred to has been soft-deleted.
|
||||
*/
|
||||
deleted?: boolean;
|
||||
/**
|
||||
* Optional description of entity.
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* Display Name that identifies this entity.
|
||||
*/
|
||||
displayName?: string;
|
||||
/**
|
||||
* Fully qualified name of the entity instance. For entities such as tables, databases
|
||||
* fullyQualifiedName is returned in this field. For entities that don't have name hierarchy
|
||||
* such as `user` and `team` this will be same as the `name` field.
|
||||
*/
|
||||
fullyQualifiedName?: string;
|
||||
/**
|
||||
* Link to the entity resource.
|
||||
*/
|
||||
href?: string;
|
||||
/**
|
||||
* Unique identifier that identifies an entity instance.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* If true the relationship indicated by this entity reference is inherited from the parent
|
||||
* entity.
|
||||
*/
|
||||
inherited?: boolean;
|
||||
/**
|
||||
* Name of the entity instance.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* Entity type/class name - Examples: `database`, `table`, `metrics`, `databaseService`,
|
||||
* `dashboardService`...
|
||||
*/
|
||||
type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of provider of an entity. Some entities are provided by the `system`. Some are
|
||||
* entities created and provided by the `user`. Typically `system` provide entities can't be
|
||||
|
@ -66,6 +66,10 @@ export interface Classification {
|
||||
*/
|
||||
mutuallyExclusive?: boolean;
|
||||
name: string;
|
||||
/**
|
||||
* Owners of this Classification.
|
||||
*/
|
||||
owners?: EntityReference[];
|
||||
provider?: ProviderType;
|
||||
/**
|
||||
* Total number of children tag terms under this classification. This includes all the
|
||||
@ -164,6 +168,13 @@ export interface FieldChange {
|
||||
* EntityReference is used for capturing relationships from one entity to another. For
|
||||
* example, a table has an attribute called database of type EntityReference that captures
|
||||
* the relationship of a table `belongs to a` database.
|
||||
*
|
||||
* Owners of this Classification.
|
||||
*
|
||||
* This schema defines the EntityReferenceList type used for referencing an entity.
|
||||
* EntityReference is used for capturing relationships from one entity to another. For
|
||||
* example, a table has an attribute called database of type EntityReference that captures
|
||||
* the relationship of a table `belongs to a` database.
|
||||
*/
|
||||
export interface EntityReference {
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user