diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/EntityResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/EntityResource.java index bd3d266fdfd..df88919e930 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/EntityResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/EntityResource.java @@ -1,6 +1,8 @@ package org.openmetadata.service.resources; import static org.openmetadata.common.utils.CommonUtil.listOrEmpty; +import static org.openmetadata.schema.type.MetadataOperation.CREATE; +import static org.openmetadata.schema.type.MetadataOperation.EDIT_ALL; import java.io.IOException; import java.util.List; @@ -182,7 +184,7 @@ public abstract class EntityResource response = dao.createOrUpdate(uriInfo, entity); addHref(uriInfo, response.getEntity()); return response.toResponse(); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/settings/SettingsResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/settings/SettingsResource.java index 5ae95a50d90..fda7a9a75b2 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/settings/SettingsResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/settings/SettingsResource.java @@ -64,6 +64,10 @@ import org.openmetadata.service.util.ResultList; @Consumes(MediaType.APPLICATION_JSON) @Collection(name = "settings") @Slf4j +/** + * Resource for managing OpenMetadata settings that an admin can change. Example - using APIs here, the conversation + * thread notification can be changed to include only events that an organization uses. + */ public class SettingsResource { private final SettingsRepository settingsRepository; private final Authorizer authorizer; @@ -236,6 +240,7 @@ public class SettingsResource { @PathParam("entityName") String entityName, @Valid List newFilter) { + authorizer.authorizeAdmin(securityContext, false); return settingsRepository.updateEntityFilter(entityName, newFilter); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/UserResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/UserResource.java index 24bd91d69eb..fcfd6f2373f 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/UserResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/UserResource.java @@ -24,6 +24,8 @@ import static org.openmetadata.schema.auth.TokenType.PASSWORD_RESET; import static org.openmetadata.schema.auth.TokenType.REFRESH_TOKEN; import static org.openmetadata.schema.entity.teams.AuthenticationMechanism.AuthType.BASIC; import static org.openmetadata.schema.entity.teams.AuthenticationMechanism.AuthType.JWT; +import static org.openmetadata.schema.type.MetadataOperation.CREATE; +import static org.openmetadata.schema.type.MetadataOperation.EDIT_ALL; import static org.openmetadata.service.exception.CatalogExceptionMessage.EMAIL_SENDING_ISSUE; import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_USERNAME_PASSWORD; import static org.openmetadata.service.exception.CatalogExceptionMessage.MAX_FAILED_LOGIN_ATTEMPT; @@ -544,17 +546,21 @@ public class UserResource extends EntityResource { public Response createOrUpdateUser( @Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateUser create) throws IOException { User user = getUser(securityContext, create); + + // If entity does not exist, this is a create operation, else update operation + ResourceContext resourceContext = getResourceContextByName(user.getFullyQualifiedName()); + MetadataOperation operation = resourceContext.getEntity() == null ? CREATE : EDIT_ALL; + dao.prepare(user); if (Boolean.TRUE.equals(create.getIsAdmin()) || Boolean.TRUE.equals(create.getIsBot())) { authorizer.authorizeAdmin(securityContext, true); } else if (!securityContext.getUserPrincipal().getName().equals(user.getName())) { // doing authorization check outside of authorizer here. We are checking if the logged-in user same as the user - // we are trying to update. One option is to set users.owner as user, however thats not supported User entity. - OperationContext createOperationContext = new OperationContext(entityType, MetadataOperation.CREATE); - ResourceContext resourceContext = getResourceContextByName(user.getName()); + // we are trying to update. One option is to set users.owner as user, however that is not supported for User. + OperationContext createOperationContext = new OperationContext(entityType, operation); authorizer.authorize(securityContext, createOperationContext, resourceContext); } - if (Boolean.TRUE.equals(create.getIsBot())) { + if (Boolean.TRUE.equals(create.getIsBot())) { // TODO expect bot to be created separately return createOrUpdateBot(user, create, uriInfo, securityContext); } RestUtil.PutResponse response = dao.createOrUpdate(uriInfo, user); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/usage/UsageResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/usage/UsageResource.java index aa1bf2a5c58..d4815b54d0b 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/usage/UsageResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/usage/UsageResource.java @@ -259,7 +259,7 @@ public class UsageResource { content = @Content(mediaType = "application/json", schema = @Schema(implementation = EntityUsage.class))), @ApiResponse(responseCode = "400", description = "Bad request") }) - public Response createorUpdateByName( + public Response createOrUpdateByName( @Context UriInfo uriInfo, @Parameter( description = "Entity type for which usage is reported", diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectCache.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectCache.java index c85f82c37ae..5f22e7c7d86 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectCache.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectCache.java @@ -114,10 +114,6 @@ public class SubjectCache { } } - public List getInheritedRolesForUser(String userName) { - return getRolesForTeams(getSubjectContext(userName).getTeams()); - } - public List getRolesForTeams(List teams) { List roles = new ArrayList<>(); for (EntityReference teamRef : listOrEmpty(teams)) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectContext.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectContext.java index 8fd796fbeae..2765d3b3cb5 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectContext.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/SubjectContext.java @@ -224,9 +224,12 @@ public class SubjectContext { iterators.add(new RolePolicyIterator(Entity.USER, user.getName(), user.getRoles())); } - // Finally, iterate over policies of teams to which the user belongs to - for (EntityReference team : user.getTeams()) { - iterators.add(new TeamPolicyIterator(team.getId(), teamsVisited)); + if (!Boolean.TRUE.equals(user.getIsBot())) { + // Finally, iterate over policies of teams to which the user belongs to + // Note that ** Bots don't inherit policies or default roles from teams ** + for (EntityReference team : user.getTeams()) { + iterators.add(new TeamPolicyIterator(team.getId(), teamsVisited)); + } } } diff --git a/openmetadata-service/src/main/resources/json/data/role/DataQualityBotRole.json b/openmetadata-service/src/main/resources/json/data/role/DataQualityBotRole.json index 064bdbf3b6c..701cc5745e8 100644 --- a/openmetadata-service/src/main/resources/json/data/role/DataQualityBotRole.json +++ b/openmetadata-service/src/main/resources/json/data/role/DataQualityBotRole.json @@ -10,7 +10,7 @@ }, { "type" : "policy", - "name" : "DataQualityBotPolicy" + "name" : "QualityBotPolicy" } ] } diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/EntityResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/EntityResourceTest.java index d58056c904b..4bcc4fc322b 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/EntityResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/EntityResourceTest.java @@ -1008,7 +1008,7 @@ public abstract class EntityResourceTest updateEntity(updateRequest, OK, TEST_AUTH_HEADERS), FORBIDDEN, - permissionNotAllowed(TEST_USER_NAME, List.of(MetadataOperation.CREATE))); + permissionNotAllowed(TEST_USER_NAME, List.of(MetadataOperation.EDIT_ALL))); } @Test diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/bots/BotResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/bots/BotResourceTest.java index 91aace5ceeb..beefeb7b8c9 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/bots/BotResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/bots/BotResourceTest.java @@ -64,13 +64,6 @@ public class BotResourceTest extends EntityResourceTest { } } - @Test - void put_entityNonEmptyDescriptionUpdate_200(TestInfo test) { - // PUT based updates are categorized as create operation - // PUT from a bot to update itself is rejected because of that - // TODO turning off the test for now which requires BOT to make update using PUT - } - @Test void delete_ensureBotUserDelete(TestInfo test) throws IOException { User testUser = new UserResourceTest().createUser("test-deleter", true);