diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java index 5d24a5418e7..5ac078bfa23 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java @@ -76,8 +76,8 @@ import org.openmetadata.service.util.ResultList; @Slf4j public class TeamRepository extends EntityRepository { - static final String TEAM_UPDATE_FIELDS = "owner,profile,users,defaultRoles,parents,children,policies,teamType"; - static final String TEAM_PATCH_FIELDS = "owner,profile,users,defaultRoles,parents,children,policies,teamType"; + static final String TEAM_UPDATE_FIELDS = "owner,profile,users,defaultRoles,parents,children,policies,teamType,email"; + static final String TEAM_PATCH_FIELDS = "owner,profile,users,defaultRoles,parents,children,policies,teamType,email"; private static final String DEFAULT_ROLES = "defaultRoles"; private Team organization = null; @@ -660,6 +660,7 @@ public class TeamRepository extends EntityRepository { recordChange("profile", original.getProfile(), updated.getProfile()); recordChange("isJoinable", original.getIsJoinable(), updated.getIsJoinable()); recordChange("teamType", original.getTeamType(), updated.getTeamType()); + recordChange("email", original.getEmail(), updated.getEmail()); updateUsers(original, updated); updateDefaultRoles(original, updated); updateParents(original, updated); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/TeamResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/TeamResource.java index fe11ff2a907..0f544967a49 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/TeamResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/TeamResource.java @@ -516,6 +516,7 @@ public class TeamResource extends EntityResource { .withTeamType(ct.getTeamType()) .withParents(EntityUtil.toEntityReferences(ct.getParents(), Entity.TEAM)) .withChildren(EntityUtil.toEntityReferences(ct.getChildren(), Entity.TEAM)) - .withPolicies(EntityUtil.toEntityReferences(ct.getPolicies(), Entity.POLICY)); + .withPolicies(EntityUtil.toEntityReferences(ct.getPolicies(), Entity.POLICY)) + .withEmail(ct.getEmail()); } } diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/teams/TeamResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/teams/TeamResourceTest.java index 8c35fd3223c..bb502afab15 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/teams/TeamResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/teams/TeamResourceTest.java @@ -57,6 +57,7 @@ import static org.openmetadata.service.util.TestUtils.validateEntityReferences; import com.fasterxml.jackson.core.JsonProcessingException; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -93,7 +94,9 @@ import org.openmetadata.schema.type.ImageList; import org.openmetadata.schema.type.Include; import org.openmetadata.schema.type.MetadataOperation; import org.openmetadata.schema.type.Profile; +import org.openmetadata.schema.type.Webhook; import org.openmetadata.schema.type.csv.CsvImportResult; +import org.openmetadata.schema.type.profile.SubscriptionConfig; import org.openmetadata.service.Entity; import org.openmetadata.service.exception.CatalogExceptionMessage; import org.openmetadata.service.jdbi3.TeamRepository.TeamCsv; @@ -668,6 +671,51 @@ public class TeamResourceTest extends EntityResourceTest { patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); } + @Test + void patch_teamEmail(TestInfo test) throws IOException { + CreateTeam create = createRequest(getEntityName(test)); + Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS); + + // Add policies to the team + String json = JsonUtils.pojoToJson(team); + String email = String.format("%s@openmetadata.org", team.getName()); + team.withEmail(email); + ChangeDescription change = getChangeDescription(team.getVersion()); + fieldAdded(change, "email", email); + team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); + + // Remove policies from the team + json = JsonUtils.pojoToJson(team); + team.withEmail(null); + change = getChangeDescription(team.getVersion()); + fieldDeleted(change, "email", email); + patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); + } + + @Test + void patch_ProfileWithSubscription(TestInfo test) throws IOException, URISyntaxException { + CreateTeam create = createRequest(getEntityName(test)); + Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS); + Profile profile1 = + new Profile() + .withSubscription( + new SubscriptionConfig().withSlack(new Webhook().withEndpoint(new URI("http://example.com")))); + + // Add policies to the team + String json = JsonUtils.pojoToJson(team); + team.withProfile(profile1); + ChangeDescription change = getChangeDescription(team.getVersion()); + fieldUpdated(change, "profile", PROFILE, profile1); + team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); + + // Remove policies from the team + json = JsonUtils.pojoToJson(team); + team.withProfile(null); + change = getChangeDescription(team.getVersion()); + fieldDeleted(change, "profile", profile1); + patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); + } + @Test void testInheritedRole() throws HttpResponseException { // team11 inherits DATA_CONSUMER_ROLE from Organization @@ -819,6 +867,7 @@ public class TeamResourceTest extends EntityResourceTest { @Override public void validateCreatedEntity(Team team, CreateTeam createRequest, Map authHeaders) { assertEquals(createRequest.getProfile(), team.getProfile()); + assertEquals(createRequest.getEmail(), team.getEmail()); TestUtils.validateEntityReferences(team.getOwns()); List expectedUsers = new ArrayList<>(); @@ -850,6 +899,7 @@ public class TeamResourceTest extends EntityResourceTest { public void compareEntities(Team expected, Team updated, Map authHeaders) { assertEquals(expected.getDisplayName(), updated.getDisplayName()); assertEquals(expected.getProfile(), updated.getProfile()); + assertEquals(expected.getEmail(), updated.getEmail()); TestUtils.validateEntityReferences(updated.getOwns()); List expectedUsers = listOrEmpty(expected.getUsers()); @@ -871,6 +921,10 @@ public class TeamResourceTest extends EntityResourceTest { List expectedRefs = (List) expected; List actualRefs = JsonUtils.readObjects(actual.toString(), EntityReference.class); assertEntityReferences(expectedRefs, actualRefs); + } else if (fieldName.equals("profile")) { + Profile expectedProfile = (Profile) expected; + Profile actualProfile = JsonUtils.convertValue(actual, Profile.class); + assertEquals(expectedProfile, actualProfile); } else { assertCommonFieldChange(fieldName, expected, actual); } diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/teams/UserResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/teams/UserResourceTest.java index 153f6730e3f..1366914889b 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/teams/UserResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/teams/UserResourceTest.java @@ -64,6 +64,7 @@ import com.auth0.jwt.interfaces.DecodedJWT; import com.fasterxml.jackson.core.JsonProcessingException; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; @@ -112,7 +113,9 @@ import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.ImageList; import org.openmetadata.schema.type.MetadataOperation; import org.openmetadata.schema.type.Profile; +import org.openmetadata.schema.type.Webhook; import org.openmetadata.schema.type.csv.CsvImportResult; +import org.openmetadata.schema.type.profile.SubscriptionConfig; import org.openmetadata.service.Entity; import org.openmetadata.service.auth.JwtResponse; import org.openmetadata.service.exception.CatalogExceptionMessage; @@ -1075,6 +1078,30 @@ public class UserResourceTest extends EntityResourceTest { assertNotNull(createDifferentBotUser); } + @Test + void patch_ProfileWithSubscription(TestInfo test) throws IOException, URISyntaxException { + CreateUser create = createRequest(test, 1); + User user = createAndCheckEntity(create, ADMIN_AUTH_HEADERS); + Profile profile1 = + new Profile() + .withSubscription( + new SubscriptionConfig().withSlack(new Webhook().withEndpoint(new URI("http://example.com")))); + + // Add policies to the team + String json = JsonUtils.pojoToJson(user); + user.withProfile(profile1); + ChangeDescription change = getChangeDescription(user.getVersion()); + fieldUpdated(change, "profile", PROFILE, profile1); + user = patchEntityAndCheck(user, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); + + // Remove policies from the team + json = JsonUtils.pojoToJson(user); + user.withProfile(null); + change = getChangeDescription(user.getVersion()); + fieldDeleted(change, "profile", profile1); + patchEntityAndCheck(user, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); + } + private DecodedJWT decodedJWT(String token) { DecodedJWT jwt; try { diff --git a/openmetadata-spec/src/main/resources/json/schema/api/teams/createTeam.json b/openmetadata-spec/src/main/resources/json/schema/api/teams/createTeam.json index 1abbbb7826f..a1d2bcc39ee 100644 --- a/openmetadata-spec/src/main/resources/json/schema/api/teams/createTeam.json +++ b/openmetadata-spec/src/main/resources/json/schema/api/teams/createTeam.json @@ -15,6 +15,10 @@ "name": { "$ref": "../../type/basic.json#/definitions/entityName" }, + "email": { + "description": "Email address of the team.", + "$ref": "../../type/basic.json#/definitions/email" + }, "displayName": { "description": "Optional name used for display purposes. Example 'Marketing Team'.", "type": "string" diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/teams/team.json b/openmetadata-spec/src/main/resources/json/schema/entity/teams/team.json index 5be05a4d92b..0249e386189 100644 --- a/openmetadata-spec/src/main/resources/json/schema/entity/teams/team.json +++ b/openmetadata-spec/src/main/resources/json/schema/entity/teams/team.json @@ -32,6 +32,10 @@ "description": "A unique name of the team typically the team ID from an identity provider. Example - group Id from LDAP.", "$ref": "../../type/basic.json#/definitions/entityName" }, + "email": { + "description": "Email address of the team.", + "$ref": "../../type/basic.json#/definitions/email" + }, "fullyQualifiedName": { "description": "FullyQualifiedName same as `name`.", "$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName" diff --git a/openmetadata-spec/src/main/resources/json/schema/type/profile.json b/openmetadata-spec/src/main/resources/json/schema/type/profile.json index cb1cb4afa7c..f64dc2e1feb 100644 --- a/openmetadata-spec/src/main/resources/json/schema/type/profile.json +++ b/openmetadata-spec/src/main/resources/json/schema/type/profile.json @@ -6,6 +6,23 @@ "type": "object", "javaType": "org.openmetadata.schema.type.Profile", "definitions": { + "messagingProvider": { + "javaType": "org.openmetadata.schema.type.profile.SubscriptionConfig", + "description": "Holds the Subscription Config for different types", + "type": "object", + "properties": { + "slack": { + "$ref": "../entity/events/webhook.json" + }, + "msTeams": { + "$ref": "../entity/events/webhook.json" + }, + "gChat": { + "$ref": "../entity/events/webhook.json" + } + }, + "additionalProperties": false + }, "imageList": { "description": "Links to a list of images of varying resolutions/sizes.", "type": "object", @@ -46,6 +63,9 @@ "properties": { "images": { "$ref": "#/definitions/imageList" + }, + "subscription": { + "$ref": "#/definitions/messagingProvider" } }, "additionalProperties": false