Fixes #3693 Move POST, PUT, PATCH, and DELETE implementations to EntityResource (#3694)

This commit is contained in:
Suresh Srinivas 2022-03-27 15:03:06 -07:00 committed by GitHub
parent c3154afd2d
commit 4577f12bfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 366 additions and 605 deletions

View File

@ -42,6 +42,7 @@ public class DashboardServiceRepository extends EntityRepository<DashboardServic
dao,
"",
UPDATE_FIELDS);
this.allowEdits = true;
}
@Override

View File

@ -53,6 +53,7 @@ public class DatabaseServiceRepository extends EntityRepository<DatabaseService>
"",
UPDATE_FIELDS);
fernet = Fernet.getInstance();
this.allowEdits = true;
}
public void rotate() throws IOException {

View File

@ -118,6 +118,7 @@ public abstract class EntityRepository<T> {
protected final boolean supportsTags;
protected final boolean supportsOwner;
protected final boolean supportsFollower;
protected boolean allowEdits = false;
/** Fields that can be updated during PATCH operation */
private final Fields patchFields;
@ -370,14 +371,8 @@ public abstract class EntityRepository<T> {
return createNewEntity(entity);
}
public final PutResponse<T> createOrUpdate(UriInfo uriInfo, T updated) throws IOException, ParseException {
// By default, do not allow updates on original description or display names of entities
return createOrUpdate(uriInfo, updated, false);
}
@Transaction
public final PutResponse<T> createOrUpdate(UriInfo uriInfo, T updated, boolean allowEdits)
throws IOException, ParseException {
public final PutResponse<T> createOrUpdate(UriInfo uriInfo, T updated) throws IOException, ParseException {
prepare(updated);
EntityInterface<T> updatedInterface = getEntityInterface(updated);
@ -397,7 +392,7 @@ public abstract class EntityRepository<T> {
// Update the attributes and relationships of an entity
EntityUpdater entityUpdater = getUpdater(original, updated, Operation.PUT);
entityUpdater.update(allowEdits);
entityUpdater.update();
String change = entityUpdater.fieldsChanged() ? RestUtil.ENTITY_UPDATED : RestUtil.ENTITY_NO_CHANGE;
return new PutResponse<>(Status.OK, withHref(uriInfo, updated), change);
}
@ -459,10 +454,6 @@ public abstract class EntityRepository<T> {
}
@Transaction
public final DeleteResponse<T> delete(String updatedBy, String id) throws IOException, ParseException {
return delete(updatedBy, id, false, false);
}
public final DeleteResponse<T> delete(String updatedBy, String id, boolean recursive)
throws IOException, ParseException {
return delete(updatedBy, id, recursive, false);
@ -572,7 +563,7 @@ public abstract class EntityRepository<T> {
}
}
public final EntityReference getOriginalOwner(T entity) throws IOException, ParseException {
public EntityReference getOriginalOwner(T entity) throws IOException, ParseException {
if (!supportsOwner) {
return null;
}
@ -884,19 +875,15 @@ public abstract class EntityRepository<T> {
this.operation = operation;
}
public final void update() throws IOException, ParseException {
update(false);
}
/** Compare original and updated entities and perform updates. Update the entity version and track changes. */
public final void update(boolean allowEdits) throws IOException, ParseException {
public final void update() throws IOException, ParseException {
if (operation.isDelete()) { // DELETE Operation
updateDeleted();
} else { // PUT or PATCH operations
updated.setId(original.getId());
updateDeleted();
updateDescription(allowEdits);
updateDisplayName(allowEdits);
updateDescription();
updateDisplayName();
updateOwner();
updateTags(updated.getFullyQualifiedName(), "tags", original.getTags(), updated.getTags());
entitySpecificUpdate();
@ -910,7 +897,7 @@ public abstract class EntityRepository<T> {
// Default implementation. Override this to add any entity specific field updates
}
private void updateDescription(boolean allowEdits) throws JsonProcessingException {
private void updateDescription() throws JsonProcessingException {
if (operation.isPut()
&& original.getDescription() != null
&& !original.getDescription().isEmpty()
@ -939,7 +926,7 @@ public abstract class EntityRepository<T> {
}
}
private void updateDisplayName(boolean allowEdits) throws JsonProcessingException {
private void updateDisplayName() throws JsonProcessingException {
if (operation.isPut()
&& original.getDisplayName() != null
&& !original.getDisplayName().isEmpty()

View File

@ -25,7 +25,6 @@ import java.net.URI;
import java.text.ParseException;
import java.util.List;
import java.util.UUID;
import org.jdbi.v3.sqlobject.transaction.Transaction;
import org.openmetadata.catalog.Entity;
import org.openmetadata.catalog.entity.data.Glossary;
import org.openmetadata.catalog.resources.glossary.GlossaryResource;
@ -54,11 +53,6 @@ public class GlossaryRepository extends EntityRepository<Glossary> {
UPDATE_FIELDS);
}
@Transaction
public EntityReference getOwnerReference(Glossary glossary) throws IOException {
return EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), glossary.getOwner());
}
@Override
public Glossary setFields(Glossary glossary, Fields fields) throws IOException, ParseException {
glossary.setOwner(fields.contains(FIELD_OWNER) ? getOwner(glossary) : null);

View File

@ -43,6 +43,7 @@ public class MessagingServiceRepository extends EntityRepository<MessagingServic
dao,
"",
UPDATE_FIELDS);
this.allowEdits = true;
}
@Override

View File

@ -40,6 +40,7 @@ public class PipelineServiceRepository extends EntityRepository<PipelineService>
dao,
"",
UPDATE_FIELDS);
this.allowEdits = true;
}
@Override

View File

@ -39,6 +39,7 @@ public class StorageServiceRepository extends EntityRepository<StorageService> {
dao,
"",
UPDATE_FIELDS);
this.allowEdits = true;
}
@Override

View File

@ -60,6 +60,12 @@ public class UserRepository extends EntityRepository<User> {
return new UserEntityInterface(entity);
}
@Override
public EntityReference getOriginalOwner(User entity) throws IOException, ParseException {
// For User entity, the entity and the owner are the same
return getEntityInterface(entity).getEntityReference();
}
/** Ensures that the default roles are added for POST, PUT and PATCH operations. */
@Override
public void prepare(User user) throws IOException, ParseException {
@ -84,7 +90,7 @@ public class UserRepository extends EntityRepository<User> {
List<EntityReference> defaultRoles = new ArrayList<>();
for (EntityReference teamRef : teamsRef) {
Team team = Entity.getEntity(teamRef, new Fields(List.of("defaultRoles")), Include.NON_DELETED);
if (team != null && team.getDefaultRoles() != null) {
if (team.getDefaultRoles() != null) {
defaultRoles.addAll(team.getDefaultRoles());
}
}

View File

@ -1,29 +1,41 @@
package org.openmetadata.catalog.resources;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.text.ParseException;
import java.util.List;
import java.util.UUID;
import javax.json.JsonPatch;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
import org.openmetadata.catalog.Entity;
import org.openmetadata.catalog.jdbi3.EntityRepository;
import org.openmetadata.catalog.jdbi3.ListFilter;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityReference;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityInterface;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
public abstract class EntityResource<T, K extends EntityRepository<T>> {
protected final List<String> allowedFields;
protected final K dao;
protected final Authorizer authorizer;
private final boolean supportsOwner;
public EntityResource(Class<T> entityClass, K repository, Authorizer authorizer) {
allowedFields = Entity.getEntityFields(entityClass);
supportsOwner = allowedFields.contains(FIELD_OWNER);
this.dao = repository;
this.authorizer = authorizer;
}
@ -72,4 +84,41 @@ public abstract class EntityResource<T, K extends EntityRepository<T>> {
Fields fields = getFields(fieldsParam);
return addHref(uriInfo, dao.getByName(uriInfo, name, fields, include));
}
public Response create(UriInfo uriInfo, SecurityContext securityContext, T entity, int flags)
throws IOException, ParseException {
SecurityUtil.authorizeAdmin(authorizer, securityContext, flags);
entity = addHref(uriInfo, dao.create(uriInfo, entity));
EntityInterface<T> entityInterface = dao.getEntityInterface(entity);
return Response.created(entityInterface.getHref()).entity(entity).build();
}
public Response createOrUpdate(UriInfo uriInfo, SecurityContext securityContext, T entity, int checkFlags)
throws IOException, ParseException {
EntityReference owner = SecurityUtil.checkOwner(checkFlags) ? dao.getOriginalOwner(entity) : null;
SecurityUtil.authorize(authorizer, securityContext, null, owner, checkFlags);
PutResponse<T> response = dao.createOrUpdate(uriInfo, entity);
addHref(uriInfo, response.getEntity());
return response.toResponse();
}
public Response patchInternal(UriInfo uriInfo, SecurityContext securityContext, String id, JsonPatch patch)
throws IOException, ParseException {
T entity = dao.get(uriInfo, id, supportsOwner ? getFields(FIELD_OWNER) : Fields.EMPTY_FIELDS);
EntityInterface<T> entityInterface = dao.getEntityInterface(entity);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer, securityContext, entityInterface.getEntityReference(), entityInterface.getOwner(), patch);
PatchResponse<T> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
}
public Response delete(UriInfo uriInfo, SecurityContext securityContext, String id, boolean recursive, int checkFlags)
throws IOException, ParseException {
SecurityUtil.authorizeAdmin(authorizer, securityContext, checkFlags);
DeleteResponse<T> response = dao.delete(securityContext.getUserPrincipal().getName(), id, recursive);
addHref(uriInfo, response.getEntity());
return response.toResponse();
}
}

View File

@ -13,6 +13,8 @@
package org.openmetadata.catalog.resources.bots;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@ -46,7 +48,6 @@ import org.openmetadata.catalog.jdbi3.ListFilter;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.ResultList;
@ -130,11 +131,9 @@ public class BotsResource extends EntityResource<Bots, BotsRepository> {
})
public Response create(@Context UriInfo uriInfo, @Context SecurityContext securityContext, Bots bot)
throws IOException, ParseException {
SecurityUtil.checkAdminRole(authorizer, securityContext);
bot.withId(UUID.randomUUID())
.withUpdatedBy(securityContext.getUserPrincipal().getName())
.withUpdatedAt(System.currentTimeMillis());
dao.create(uriInfo, bot);
return Response.created(bot.getHref()).entity(bot).build();
return create(uriInfo, securityContext, bot, ADMIN);
}
}

View File

@ -13,6 +13,10 @@
package org.openmetadata.catalog.resources.charts;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation;
@ -56,15 +60,9 @@ import org.openmetadata.catalog.jdbi3.ListFilter;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityInterface;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/charts")
@ -275,10 +273,8 @@ public class ChartResource extends EntityResource<Chart, ChartRepository> {
})
public Response create(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateChart create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Chart chart = getChart(securityContext, create);
chart = addHref(uriInfo, dao.create(uriInfo, chart));
return Response.created(chart.getHref()).entity(chart).build();
return create(uriInfo, securityContext, chart, ADMIN | BOT);
}
@PATCH
@ -289,7 +285,7 @@ public class ChartResource extends EntityResource<Chart, ChartRepository> {
description = "Update an existing chart using JsonPatch.",
externalDocs = @ExternalDocumentation(description = "JsonPatch RFC", url = "https://tools.ietf.org/html/rfc6902"))
@Consumes(MediaType.APPLICATION_JSON_PATCH_JSON)
public Response updateDescription(
public Response patch(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@PathParam("id") String id,
@ -303,16 +299,7 @@ public class ChartResource extends EntityResource<Chart, ChartRepository> {
}))
JsonPatch patch)
throws IOException, ParseException {
Fields fields = getFields(Entity.FIELD_OWNER);
Chart chart = dao.get(uriInfo, id, fields);
EntityInterface<Chart> entityInterface = dao.getEntityInterface(chart);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer, securityContext, entityInterface.getEntityReference(), entityInterface.getOwner(), patch);
PatchResponse<Chart> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@PUT
@ -330,10 +317,7 @@ public class ChartResource extends EntityResource<Chart, ChartRepository> {
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateChart create)
throws IOException, ParseException {
Chart chart = getChart(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(chart));
PutResponse<Chart> response = dao.createOrUpdate(uriInfo, chart);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, chart, ADMIN | BOT | OWNER);
}
@PUT
@ -388,9 +372,7 @@ public class ChartResource extends EntityResource<Chart, ChartRepository> {
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Chart> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
private Chart getChart(SecurityContext securityContext, CreateChart create) {

View File

@ -13,7 +13,9 @@
package org.openmetadata.catalog.resources.dashboards;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
@ -58,12 +60,8 @@ import org.openmetadata.catalog.jdbi3.ListFilter;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/dashboards")
@ -279,10 +277,8 @@ public class DashboardResource extends EntityResource<Dashboard, DashboardReposi
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateDashboard create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Dashboard dashboard = getDashboard(securityContext, create);
dashboard = addHref(uriInfo, dao.create(uriInfo, dashboard));
return Response.created(dashboard.getHref()).entity(dashboard).build();
return create(uriInfo, securityContext, dashboard, ADMIN | BOT);
}
@PATCH
@ -307,18 +303,7 @@ public class DashboardResource extends EntityResource<Dashboard, DashboardReposi
}))
JsonPatch patch)
throws IOException, ParseException {
Dashboard dashboard = dao.get(uriInfo, id, getFields(FIELD_OWNER));
SecurityUtil.checkAdminRoleOrPermissions(
authorizer,
securityContext,
dao.getEntityInterface(dashboard).getEntityReference(),
dao.getOwnerReference(dashboard),
patch);
PatchResponse<Dashboard> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@PUT
@ -338,10 +323,7 @@ public class DashboardResource extends EntityResource<Dashboard, DashboardReposi
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateDashboard create)
throws IOException, ParseException {
Dashboard dashboard = getDashboard(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(dashboard));
PutResponse<Dashboard> response = dao.createOrUpdate(uriInfo, dashboard);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, dashboard, ADMIN | BOT | OWNER);
}
@PUT
@ -396,9 +378,7 @@ public class DashboardResource extends EntityResource<Dashboard, DashboardReposi
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Dashboard> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
private Dashboard getDashboard(SecurityContext securityContext, CreateDashboard create) {

View File

@ -13,6 +13,10 @@
package org.openmetadata.catalog.resources.databases;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation;
@ -56,14 +60,9 @@ import org.openmetadata.catalog.jdbi3.ListFilter;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityInterface;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/databases")
@ -276,10 +275,8 @@ public class DatabaseResource extends EntityResource<Database, DatabaseRepositor
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateDatabase create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Database database = getDatabase(securityContext, create);
database = addHref(uriInfo, dao.create(uriInfo, database));
return Response.created(database.getHref()).entity(database).build();
return create(uriInfo, securityContext, database, ADMIN | BOT);
}
@PATCH
@ -304,15 +301,7 @@ public class DatabaseResource extends EntityResource<Database, DatabaseRepositor
}))
JsonPatch patch)
throws IOException, ParseException {
Database database = dao.get(uriInfo, id, getFields(Entity.FIELD_OWNER));
EntityInterface<Database> entityInterface = dao.getEntityInterface(database);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer, securityContext, entityInterface.getEntityReference(), entityInterface.getOwner(), patch);
PatchResponse<Database> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@PUT
@ -330,10 +319,7 @@ public class DatabaseResource extends EntityResource<Database, DatabaseRepositor
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateDatabase create)
throws IOException, ParseException {
Database database = getDatabase(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(database));
PutResponse<Database> response = dao.createOrUpdate(uriInfo, database);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, database, ADMIN | BOT | OWNER);
}
@DELETE
@ -368,9 +354,7 @@ public class DatabaseResource extends EntityResource<Database, DatabaseRepositor
boolean recursive,
@PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Database> response = dao.delete(securityContext.getUserPrincipal().getName(), id, recursive);
return response.toResponse();
return delete(uriInfo, securityContext, id, recursive, ADMIN | BOT);
}
private Database getDatabase(SecurityContext securityContext, CreateDatabase create) {

View File

@ -13,7 +13,9 @@
package org.openmetadata.catalog.resources.databases;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
@ -74,9 +76,6 @@ import org.openmetadata.catalog.type.TableData;
import org.openmetadata.catalog.type.TableJoins;
import org.openmetadata.catalog.type.TableProfile;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/tables")
@ -295,9 +294,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
public Response create(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateTable create)
throws IOException, ParseException {
Table table = getTable(securityContext, create);
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
table = addHref(uriInfo, dao.create(uriInfo, validateNewTable(table)));
return Response.created(table.getHref()).entity(table).build();
return create(uriInfo, securityContext, table, ADMIN | BOT);
}
@PUT
@ -316,10 +313,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateTable create)
throws IOException, ParseException {
Table table = getTable(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(table));
PutResponse<Table> response = dao.createOrUpdate(uriInfo, validateNewTable(table));
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, table, ADMIN | BOT | OWNER);
}
@PATCH
@ -344,18 +338,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
}))
JsonPatch patch)
throws IOException, ParseException {
Table table = dao.get(uriInfo, id, getFields(FIELD_OWNER));
SecurityUtil.checkAdminRoleOrPermissions(
authorizer,
securityContext,
dao.getEntityInterface(table).getEntityReference(),
dao.getOriginalOwner(table),
patch);
PatchResponse<Table> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE
@ -373,9 +356,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Context SecurityContext securityContext,
@Parameter(description = "Id of the table", schema = @Schema(type = "string")) @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Table> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
@PUT
@ -418,7 +399,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "Id of the table", schema = @Schema(type = "string")) @PathParam("id") String id,
TableJoins joins)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Table table = dao.addJoins(UUID.fromString(id), joins);
return addHref(uriInfo, table);
}
@ -432,7 +413,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "Id of the table", schema = @Schema(type = "string")) @PathParam("id") String id,
TableData tableData)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Table table = dao.addSampleData(UUID.fromString(id), tableData);
return addHref(uriInfo, table);
}
@ -446,7 +427,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "Id of the table", schema = @Schema(type = "string")) @PathParam("id") String id,
TableProfile tableProfile)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Table table = dao.addTableProfileData(UUID.fromString(id), tableProfile);
return addHref(uriInfo, table);
}
@ -480,7 +461,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "Id of the table", schema = @Schema(type = "string")) @PathParam("id") String id,
SQLQuery sqlQuery)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Table table = dao.addQuery(UUID.fromString(id), sqlQuery);
return addHref(uriInfo, table);
}
@ -497,7 +478,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "Id of the table", schema = @Schema(type = "string")) @PathParam("id") String id,
DataModel dataModel)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Table table = dao.addDataModel(UUID.fromString(id), dataModel);
return addHref(uriInfo, table);
}
@ -511,7 +492,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "Id of the table", schema = @Schema(type = "string")) @PathParam("id") String id,
CreateTableTest createTableTest)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
TableTest tableTest = getTableTest(securityContext, createTableTest);
Table table = dao.addTableTest(UUID.fromString(id), tableTest);
return addHref(uriInfo, table);
@ -527,7 +508,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "Table Test Type", schema = @Schema(type = "string")) @PathParam("tableTestType")
String tableTestType)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Table table = dao.deleteTableTest(UUID.fromString(id), tableTestType);
return addHref(uriInfo, table);
}
@ -541,7 +522,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "Id of the table", schema = @Schema(type = "string")) @PathParam("id") String id,
CreateColumnTest createColumnTest)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
ColumnTest columnTest = getColumnTest(securityContext, createColumnTest);
Table table = dao.addColumnTest(UUID.fromString(id), columnTest);
return addHref(uriInfo, table);
@ -556,7 +537,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "Id of the table", schema = @Schema(type = "string")) @PathParam("id") String id,
CreateCustomMetric createCustomMetric)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
CustomMetric customMetric = getCustomMetric(securityContext, createCustomMetric);
Table table = dao.addCustomMetric(UUID.fromString(id), customMetric);
return addHref(uriInfo, table);
@ -577,7 +558,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "column Test Type", schema = @Schema(type = "string")) @PathParam("columnTestType")
String columnTestType)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Table table = dao.deleteColumnTest(UUID.fromString(id), columnName, columnTestType);
return addHref(uriInfo, table);
}
@ -597,7 +578,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
@Parameter(description = "column Test Type", schema = @Schema(type = "string")) @PathParam("customMetricName")
String customMetricName)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Table table = dao.deleteCustomMetric(UUID.fromString(id), columnName, customMetricName);
return addHref(uriInfo, table);
}
@ -645,21 +626,22 @@ public class TableResource extends EntityResource<Table, TableRepository> {
}
private Table getTable(SecurityContext securityContext, CreateTable create) {
return new Table()
.withId(UUID.randomUUID())
.withName(create.getName())
.withColumns(create.getColumns())
.withDescription(create.getDescription())
.withTableConstraints(create.getTableConstraints())
.withTablePartition(create.getTablePartition())
.withTableType(create.getTableType())
.withTags(create.getTags())
.withViewDefinition(create.getViewDefinition())
.withProfileSample(create.getProfileSample())
.withUpdatedBy(securityContext.getUserPrincipal().getName())
.withOwner(create.getOwner())
.withUpdatedAt(System.currentTimeMillis())
.withDatabase(create.getDatabase());
return validateNewTable(
new Table()
.withId(UUID.randomUUID())
.withName(create.getName())
.withColumns(create.getColumns())
.withDescription(create.getDescription())
.withTableConstraints(create.getTableConstraints())
.withTablePartition(create.getTablePartition())
.withTableType(create.getTableType())
.withTags(create.getTags())
.withViewDefinition(create.getViewDefinition())
.withProfileSample(create.getProfileSample())
.withUpdatedBy(securityContext.getUserPrincipal().getName())
.withOwner(create.getOwner())
.withUpdatedAt(System.currentTimeMillis())
.withDatabase(create.getDatabase()));
}
private TableTest getTableTest(SecurityContext securityContext, CreateTableTest create) {

View File

@ -13,6 +13,9 @@
package org.openmetadata.catalog.resources.events;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@ -49,7 +52,6 @@ import org.openmetadata.catalog.jdbi3.WebhookRepository;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.ChangeEvent;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
@ -58,8 +60,6 @@ import org.openmetadata.catalog.type.Webhook.Status;
import org.openmetadata.catalog.util.EntityUtil;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/webhook")
@ -252,12 +252,10 @@ public class WebhookResource extends EntityResource<Webhook, WebhookRepository>
public Response createWebhook(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateWebhook create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Webhook webhook = getWebhook(securityContext, create);
webhook.setStatus(Boolean.TRUE.equals(webhook.getEnabled()) ? Status.ACTIVE : Status.DISABLED);
webhook = dao.create(uriInfo, webhook);
Response response = create(uriInfo, securityContext, webhook, ADMIN);
dao.addWebhookPublisher(webhook);
return Response.created(webhook.getHref()).entity(webhook).build();
return response;
}
@PUT
@ -275,12 +273,10 @@ public class WebhookResource extends EntityResource<Webhook, WebhookRepository>
public Response updateWebhook(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateWebhook create)
throws IOException, ParseException, InterruptedException {
SecurityUtil.checkAdminRole(authorizer, securityContext);
Webhook webhook = getWebhook(securityContext, create);
webhook.setStatus(Boolean.TRUE.equals(webhook.getEnabled()) ? Status.ACTIVE : Status.DISABLED);
PutResponse<Webhook> putResponse = dao.createOrUpdate(uriInfo, webhook);
dao.updateWebhookPublisher(webhook);
return putResponse.toResponse();
Response response = createOrUpdate(uriInfo, securityContext, webhook, ADMIN | BOT);
dao.updateWebhookPublisher((Webhook) response.getEntity());
return response;
}
@DELETE
@ -302,10 +298,9 @@ public class WebhookResource extends EntityResource<Webhook, WebhookRepository>
@Context SecurityContext securityContext,
@Parameter(description = "webhook Id", schema = @Schema(type = "string")) @PathParam("id") String id)
throws IOException, ParseException, InterruptedException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Webhook> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
Response response = delete(uriInfo, securityContext, id, false, ADMIN);
dao.deleteWebhookPublisher(UUID.fromString(id));
return response.toResponse();
return response;
}
public Webhook getWebhook(SecurityContext securityContext, CreateWebhook create) {
@ -322,6 +317,7 @@ public class WebhookResource extends EntityResource<Webhook, WebhookRepository>
.withEnabled(create.getEnabled())
.withUpdatedBy(securityContext.getUserPrincipal().getName())
.withUpdatedAt(System.currentTimeMillis())
.withSecretKey(create.getSecretKey());
.withSecretKey(create.getSecretKey())
.withStatus(Boolean.TRUE.equals(create.getEnabled()) ? Status.ACTIVE : Status.DISABLED);
}
}

View File

@ -13,6 +13,10 @@
package org.openmetadata.catalog.resources.feeds;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
@ -326,7 +330,7 @@ public class FeedResource {
Thread thread = dao.get(threadId);
Post post = dao.getPostById(thread, postId);
// delete post only if the admin/bot/author tries to delete it
SecurityUtil.checkAdminOrBotOrOwner(authorizer, securityContext, dao.getOwnerOfPost(post));
SecurityUtil.authorize(authorizer, securityContext, null, dao.getOwnerOfPost(post), ADMIN | BOT | OWNER);
return dao.deletePost(thread, post, securityContext.getUserPrincipal().getName()).toResponse();
}

View File

@ -13,6 +13,10 @@
package org.openmetadata.catalog.resources.glossary;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import com.google.inject.Inject;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
@ -57,13 +61,9 @@ import org.openmetadata.catalog.jdbi3.ListFilter;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/glossaries")
@ -274,10 +274,8 @@ public class GlossaryResource extends EntityResource<Glossary, GlossaryRepositor
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateGlossary create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Glossary glossary = getGlossary(securityContext, create);
glossary = addHref(uriInfo, dao.create(uriInfo, glossary));
return Response.created(glossary.getHref()).entity(glossary).build();
return create(uriInfo, securityContext, glossary, ADMIN | BOT);
}
@PATCH
@ -302,17 +300,7 @@ public class GlossaryResource extends EntityResource<Glossary, GlossaryRepositor
}))
JsonPatch patch)
throws IOException, ParseException {
Glossary glossary = dao.get(uriInfo, id, getFields(Entity.FIELD_OWNER));
SecurityUtil.checkAdminRoleOrPermissions(
authorizer,
securityContext,
dao.getEntityInterface(glossary).getEntityReference(),
dao.getOwnerReference(glossary),
patch);
PatchResponse<Glossary> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@PUT
@ -331,10 +319,7 @@ public class GlossaryResource extends EntityResource<Glossary, GlossaryRepositor
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateGlossary create)
throws IOException, ParseException {
Glossary glossary = getGlossary(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(glossary));
PutResponse<Glossary> response = dao.createOrUpdate(uriInfo, glossary);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, glossary, ADMIN | BOT | OWNER);
}
@DELETE
@ -349,9 +334,7 @@ public class GlossaryResource extends EntityResource<Glossary, GlossaryRepositor
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Glossary> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
private Glossary getGlossary(SecurityContext securityContext, CreateGlossary create) {

View File

@ -13,6 +13,9 @@
package org.openmetadata.catalog.resources.glossary;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import com.google.inject.Inject;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
@ -59,16 +62,11 @@ import org.openmetadata.catalog.jdbi3.ListFilter;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.EntityReference;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityInterface;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/glossaryTerms")
@ -324,10 +322,8 @@ public class GlossaryTermResource extends EntityResource<GlossaryTerm, GlossaryT
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateGlossaryTerm create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
GlossaryTerm term = getGlossaryTerm(securityContext, create);
term = addHref(uriInfo, dao.create(uriInfo, term));
return Response.created(term.getHref()).entity(term).build();
return create(uriInfo, securityContext, term, ADMIN | BOT);
}
@PATCH
@ -352,14 +348,7 @@ public class GlossaryTermResource extends EntityResource<GlossaryTerm, GlossaryT
}))
JsonPatch patch)
throws IOException, ParseException {
GlossaryTerm term = dao.get(uriInfo, id, Fields.EMPTY_FIELDS);
EntityInterface<GlossaryTerm> entityInterface = dao.getEntityInterface(term);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer, securityContext, entityInterface.getEntityReference(), entityInterface.getOwner(), patch);
PatchResponse<GlossaryTerm> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@PUT
@ -378,10 +367,7 @@ public class GlossaryTermResource extends EntityResource<GlossaryTerm, GlossaryT
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateGlossaryTerm create)
throws IOException, ParseException {
GlossaryTerm term = getGlossaryTerm(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(term));
PutResponse<GlossaryTerm> response = dao.createOrUpdate(uriInfo, term);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, term, ADMIN | BOT);
}
@DELETE
@ -396,9 +382,7 @@ public class GlossaryTermResource extends EntityResource<GlossaryTerm, GlossaryT
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<GlossaryTerm> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
private GlossaryTerm getGlossaryTerm(SecurityContext securityContext, CreateGlossaryTerm create) {

View File

@ -13,6 +13,10 @@
package org.openmetadata.catalog.resources.locations;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation;
@ -56,14 +60,10 @@ import org.openmetadata.catalog.jdbi3.LocationRepository;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/locations")
@ -331,10 +331,8 @@ public class LocationResource extends EntityResource<Location, LocationRepositor
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateLocation create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Location location = getLocation(securityContext, create);
location = addHref(uriInfo, dao.create(uriInfo, location));
return Response.created(location.getHref()).entity(location).build();
return create(uriInfo, securityContext, location, ADMIN | BOT);
}
@PUT
@ -353,10 +351,7 @@ public class LocationResource extends EntityResource<Location, LocationRepositor
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateLocation create)
throws IOException, ParseException {
Location location = getLocation(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(location));
PutResponse<Location> response = dao.createOrUpdate(uriInfo, validateNewLocation(location));
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, location, ADMIN | BOT | OWNER);
}
@PATCH
@ -381,19 +376,7 @@ public class LocationResource extends EntityResource<Location, LocationRepositor
}))
JsonPatch patch)
throws IOException, ParseException {
Fields fields = getFields(FIELDS);
Location location = dao.get(uriInfo, id, fields);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer,
securityContext,
dao.getEntityInterface(location).getEntityReference(),
dao.getOwnerReference(location),
patch);
PatchResponse<Location> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE
@ -411,9 +394,7 @@ public class LocationResource extends EntityResource<Location, LocationRepositor
@Context SecurityContext securityContext,
@Parameter(description = "Id of the location", schema = @Schema(type = "string")) @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Location> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
@PUT

View File

@ -13,6 +13,9 @@
package org.openmetadata.catalog.resources.metrics;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@ -49,7 +52,6 @@ import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/metrics")
@ -155,8 +157,7 @@ public class MetricsResource extends EntityResource<Metrics, MetricsRepository>
public Response create(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid Metrics metrics)
throws IOException, ParseException {
addToMetrics(securityContext, metrics);
dao.create(uriInfo, metrics);
return Response.created(metrics.getHref()).entity(metrics).build();
return create(uriInfo, securityContext, metrics, ADMIN | BOT);
}
@PUT
@ -175,8 +176,7 @@ public class MetricsResource extends EntityResource<Metrics, MetricsRepository>
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid Metrics metrics)
throws IOException, ParseException {
addToMetrics(securityContext, metrics);
PutResponse<Metrics> response = dao.createOrUpdate(uriInfo, metrics);
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, metrics);
}
private void addToMetrics(SecurityContext securityContext, Metrics metrics) {

View File

@ -13,6 +13,10 @@
package org.openmetadata.catalog.resources.mlmodels;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation;
@ -56,14 +60,9 @@ import org.openmetadata.catalog.jdbi3.MlModelRepository;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/mlmodels")
@ -225,10 +224,8 @@ public class MlModelResource extends EntityResource<MlModel, MlModelRepository>
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateMlModel create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
MlModel mlModel = getMlModel(securityContext, create);
mlModel = addHref(uriInfo, dao.create(uriInfo, mlModel));
return Response.created(mlModel.getHref()).entity(mlModel).build();
return create(uriInfo, securityContext, mlModel, ADMIN | BOT);
}
@PATCH
@ -253,19 +250,7 @@ public class MlModelResource extends EntityResource<MlModel, MlModelRepository>
}))
JsonPatch patch)
throws IOException, ParseException {
Fields fields = getFields(FIELDS);
MlModel mlModel = dao.get(uriInfo, id, fields);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer,
securityContext,
dao.getEntityInterface(mlModel).getEntityReference(),
dao.getOwnerReference(mlModel),
patch);
PatchResponse<MlModel> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@PUT
@ -284,10 +269,7 @@ public class MlModelResource extends EntityResource<MlModel, MlModelRepository>
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateMlModel create)
throws IOException, ParseException {
MlModel mlModel = getMlModel(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(mlModel));
PutResponse<MlModel> response = dao.createOrUpdate(uriInfo, mlModel);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, mlModel, ADMIN | BOT | OWNER);
}
@PUT
@ -393,9 +375,7 @@ public class MlModelResource extends EntityResource<MlModel, MlModelRepository>
@Context SecurityContext securityContext,
@Parameter(description = "Id of the ML Model", schema = @Schema(type = "string")) @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<MlModel> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
private MlModel getMlModel(SecurityContext securityContext, CreateMlModel create) {

View File

@ -14,6 +14,9 @@
package org.openmetadata.catalog.resources.operations;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
import io.swagger.annotations.Api;
@ -62,14 +65,9 @@ import org.openmetadata.catalog.operations.pipelines.AirflowPipeline;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityInterface;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Slf4j
@ -311,11 +309,10 @@ public class AirflowPipelineResource extends EntityResource<AirflowPipeline, Air
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateAirflowPipeline create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
AirflowPipeline airflowPipeline = getAirflowPipeline(securityContext, create);
airflowPipeline = addHref(uriInfo, dao.create(uriInfo, airflowPipeline));
Response response = create(uriInfo, securityContext, airflowPipeline, ADMIN | BOT);
deploy(airflowPipeline, true);
return Response.created(airflowPipeline.getHref()).entity(airflowPipeline).build();
return response;
}
@PATCH
@ -340,15 +337,7 @@ public class AirflowPipelineResource extends EntityResource<AirflowPipeline, Air
}))
JsonPatch patch)
throws IOException, ParseException {
AirflowPipeline airflowPipeline = dao.get(uriInfo, id, getFields(FIELD_OWNER));
EntityInterface<AirflowPipeline> entityInterface = dao.getEntityInterface(airflowPipeline);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer, securityContext, entityInterface.getEntityReference(), entityInterface.getOwner(), patch);
PatchResponse<AirflowPipeline> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@PUT
@ -368,11 +357,9 @@ public class AirflowPipelineResource extends EntityResource<AirflowPipeline, Air
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateAirflowPipeline update)
throws IOException, ParseException {
AirflowPipeline pipeline = getAirflowPipeline(securityContext, update);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(pipeline));
PutResponse<AirflowPipeline> response = dao.createOrUpdate(uriInfo, pipeline);
deploy(pipeline, SecurityUtil.isAdminOrBotRole(authorizer, securityContext));
addHref(uriInfo, response.getEntity());
return response.toResponse();
Response response = createOrUpdate(uriInfo, securityContext, pipeline, ADMIN | BOT | OWNER);
deploy(pipeline, true); // TODO cleanup
return response;
}
@POST
@ -410,12 +397,10 @@ public class AirflowPipelineResource extends EntityResource<AirflowPipeline, Air
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Fields fields = getFields(FIELD_OWNER);
AirflowPipeline pipeline = dao.get(uriInfo, id, fields);
Response response = delete(uriInfo, securityContext, id, false, ADMIN | BOT);
AirflowPipeline pipeline = (AirflowPipeline) response.getEntity();
airflowRESTClient.deletePipeline(pipeline.getName());
DeleteResponse<AirflowPipeline> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return response;
}
private AirflowPipeline getAirflowPipeline(SecurityContext securityContext, CreateAirflowPipeline create) {

View File

@ -13,6 +13,10 @@
package org.openmetadata.catalog.resources.pipelines;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation;
@ -60,11 +64,7 @@ import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/pipelines")
@ -280,10 +280,8 @@ public class PipelineResource extends EntityResource<Pipeline, PipelineRepositor
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreatePipeline create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Pipeline pipeline = getPipeline(securityContext, create);
pipeline = addHref(uriInfo, dao.create(uriInfo, pipeline));
return Response.created(pipeline.getHref()).entity(pipeline).build();
return create(uriInfo, securityContext, pipeline, ADMIN | BOT);
}
@PATCH
@ -308,19 +306,7 @@ public class PipelineResource extends EntityResource<Pipeline, PipelineRepositor
}))
JsonPatch patch)
throws IOException, ParseException {
Fields fields = getFields(FIELDS);
Pipeline pipeline = dao.get(uriInfo, id, fields);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer,
securityContext,
dao.getEntityInterface(pipeline).getEntityReference(),
dao.getOwnerReference(pipeline),
patch);
PatchResponse<Pipeline> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@PUT
@ -340,10 +326,7 @@ public class PipelineResource extends EntityResource<Pipeline, PipelineRepositor
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreatePipeline create)
throws IOException, ParseException {
Pipeline pipeline = getPipeline(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(pipeline));
PutResponse<Pipeline> response = dao.createOrUpdate(uriInfo, pipeline);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, pipeline, ADMIN | BOT | OWNER);
}
@PUT
@ -365,7 +348,7 @@ public class PipelineResource extends EntityResource<Pipeline, PipelineRepositor
@Parameter(description = "Id of the pipeline", schema = @Schema(type = "string")) @PathParam("id") String id,
PipelineStatus pipelineStatus)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Pipeline pipeline = dao.addPipelineStatus(UUID.fromString(id), pipelineStatus);
return addHref(uriInfo, pipeline);
}
@ -422,9 +405,7 @@ public class PipelineResource extends EntityResource<Pipeline, PipelineRepositor
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Pipeline> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
private Pipeline getPipeline(SecurityContext securityContext, CreatePipeline create) {

View File

@ -13,7 +13,9 @@
package org.openmetadata.catalog.resources.policies;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
@ -59,15 +61,10 @@ import org.openmetadata.catalog.jdbi3.PolicyRepository;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
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.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/policies")
@ -283,10 +280,8 @@ public class PolicyResource extends EntityResource<Policy, PolicyRepository> {
})
public Response create(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreatePolicy create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Policy policy = getPolicy(securityContext, create);
policy = addHref(uriInfo, dao.create(uriInfo, policy));
return Response.created(policy.getHref()).entity(policy).build();
return create(uriInfo, securityContext, policy, ADMIN | BOT);
}
@PATCH
@ -311,14 +306,7 @@ public class PolicyResource extends EntityResource<Policy, PolicyRepository> {
}))
JsonPatch patch)
throws IOException, ParseException {
Fields fields = getFields(FIELD_OWNER);
Policy policy = dao.get(uriInfo, id, fields);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOwnerReference(policy));
PatchResponse<Policy> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@PUT
@ -337,10 +325,7 @@ public class PolicyResource extends EntityResource<Policy, PolicyRepository> {
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreatePolicy create)
throws IOException, ParseException {
Policy policy = getPolicy(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(policy));
PutResponse<Policy> response = dao.createOrUpdate(uriInfo, policy);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, policy, ADMIN | BOT | OWNER);
}
@DELETE
@ -355,9 +340,7 @@ public class PolicyResource extends EntityResource<Policy, PolicyRepository> {
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Policy> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
private Policy getPolicy(SecurityContext securityContext, CreatePolicy create) {

View File

@ -13,6 +13,9 @@
package org.openmetadata.catalog.resources.reports;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@ -48,7 +51,6 @@ import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/reports")
@ -147,8 +149,7 @@ public class ReportResource extends EntityResource<Report, ReportRepository> {
public Response create(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid Report report)
throws IOException, ParseException {
addToReport(securityContext, report);
dao.create(uriInfo, report);
return Response.created(report.getHref()).entity(report).build();
return create(uriInfo, securityContext, report, ADMIN | BOT);
}
@PUT
@ -167,8 +168,7 @@ public class ReportResource extends EntityResource<Report, ReportRepository> {
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid Report report)
throws IOException, ParseException {
addToReport(securityContext, report);
PutResponse<Report> response = dao.createOrUpdate(uriInfo, report);
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, report);
}
private void addToReport(SecurityContext securityContext, Report report) {

View File

@ -14,6 +14,9 @@
package org.openmetadata.catalog.resources.services.dashboard;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
@ -53,12 +56,9 @@ import org.openmetadata.catalog.jdbi3.ListFilter;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/services/dashboardServices")
@ -266,10 +266,8 @@ public class DashboardServiceResource extends EntityResource<DashboardService, D
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateDashboardService create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DashboardService service = getService(create, securityContext);
service = addHref(uriInfo, dao.create(uriInfo, service));
return Response.created(service.getHref()).entity(service).build();
return create(uriInfo, securityContext, service, ADMIN | BOT);
}
@PUT
@ -291,10 +289,7 @@ public class DashboardServiceResource extends EntityResource<DashboardService, D
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateDashboardService update)
throws IOException, ParseException {
DashboardService service = getService(update, securityContext);
SecurityUtil.checkAdminOrBotOrOwner(authorizer, securityContext, dao.getOriginalOwner(service));
PutResponse<DashboardService> response = dao.createOrUpdate(uriInfo, service, true);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, service, ADMIN | BOT | OWNER);
}
@DELETE
@ -318,9 +313,7 @@ public class DashboardServiceResource extends EntityResource<DashboardService, D
@Parameter(description = "Id of the dashboard service", schema = @Schema(type = "string")) @PathParam("id")
String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<DashboardService> response = dao.delete(securityContext.getUserPrincipal().getName(), id, recursive);
return response.toResponse();
return delete(uriInfo, securityContext, id, recursive, ADMIN | BOT);
}
private DashboardService getService(CreateDashboardService create, SecurityContext securityContext) {

View File

@ -14,6 +14,10 @@
package org.openmetadata.catalog.resources.services.database;
import static org.openmetadata.catalog.fernet.Fernet.isTokenized;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
@ -24,9 +28,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.text.ParseException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.validation.Valid;
@ -66,8 +68,6 @@ import org.openmetadata.catalog.type.MetadataOperation;
import org.openmetadata.catalog.util.EntityUtil;
import org.openmetadata.catalog.util.JsonUtils;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/services/databaseServices")
@ -300,10 +300,10 @@ public class DatabaseServiceResource extends EntityResource<DatabaseService, Dat
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateDatabaseService create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DatabaseService service = getService(create, securityContext);
service = addHref(uriInfo, decryptOrNullify(securityContext, dao.create(uriInfo, service)));
return Response.created(service.getHref()).entity(service).build();
Response response = create(uriInfo, securityContext, service, ADMIN | BOT);
decryptOrNullify(securityContext, (DatabaseService) response.getEntity());
return response;
}
@PUT
@ -325,10 +325,9 @@ public class DatabaseServiceResource extends EntityResource<DatabaseService, Dat
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateDatabaseService update)
throws IOException, ParseException {
DatabaseService service = getService(update, securityContext);
SecurityUtil.checkAdminOrBotOrOwner(authorizer, securityContext, dao.getOriginalOwner(service));
PutResponse<DatabaseService> response = dao.createOrUpdate(uriInfo, service, true);
addHref(uriInfo, decryptOrNullify(securityContext, response.getEntity()));
return response.toResponse();
Response response = createOrUpdate(uriInfo, securityContext, service, ADMIN | BOT | OWNER);
decryptOrNullify(securityContext, (DatabaseService) response.getEntity());
return response;
}
@DELETE
@ -352,16 +351,14 @@ public class DatabaseServiceResource extends EntityResource<DatabaseService, Dat
@Parameter(description = "Id of the database service", schema = @Schema(type = "string")) @PathParam("id")
String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<DatabaseService> response = dao.delete(securityContext.getUserPrincipal().getName(), id, recursive);
decryptOrNullify(securityContext, response.getEntity());
return response.toResponse();
Response response = delete(uriInfo, securityContext, id, recursive, ADMIN | BOT);
decryptOrNullify(securityContext, (DatabaseService) response.getEntity());
return response;
}
private ResultList<DatabaseService> decryptOrNullify(
SecurityContext securityContext, ResultList<DatabaseService> databaseServices) {
Optional.ofNullable(databaseServices.getData())
.orElse(Collections.emptyList())
listOrEmpty(databaseServices.getData())
.forEach(databaseService -> decryptOrNullify(securityContext, databaseService));
return databaseServices;
}

View File

@ -14,6 +14,9 @@
package org.openmetadata.catalog.resources.services.messaging;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
@ -53,12 +56,9 @@ import org.openmetadata.catalog.jdbi3.MessagingServiceRepository;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/services/messagingServices")
@ -269,10 +269,8 @@ public class MessagingServiceResource extends EntityResource<MessagingService, M
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateMessagingService create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
MessagingService service = getService(create, securityContext);
service = addHref(uriInfo, dao.create(uriInfo, service));
return Response.created(service.getHref()).entity(service).build();
return create(uriInfo, securityContext, service, ADMIN | BOT);
}
@PUT
@ -298,10 +296,7 @@ public class MessagingServiceResource extends EntityResource<MessagingService, M
@Valid CreateMessagingService update)
throws IOException, ParseException {
MessagingService service = getService(update, securityContext);
SecurityUtil.checkAdminOrBotOrOwner(authorizer, securityContext, dao.getOriginalOwner(service));
PutResponse<MessagingService> response = dao.createOrUpdate(uriInfo, service, true);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, service, ADMIN | BOT | OWNER);
}
@DELETE
@ -324,9 +319,7 @@ public class MessagingServiceResource extends EntityResource<MessagingService, M
@Parameter(description = "Id of the messaging service", schema = @Schema(type = "string")) @PathParam("id")
String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<MessagingService> response = dao.delete(securityContext.getUserPrincipal().getName(), id, recursive);
return response.toResponse();
return delete(uriInfo, securityContext, id, recursive, ADMIN | BOT);
}
private MessagingService getService(CreateMessagingService create, SecurityContext securityContext) {

View File

@ -14,6 +14,9 @@
package org.openmetadata.catalog.resources.services.pipeline;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
@ -53,12 +56,9 @@ import org.openmetadata.catalog.jdbi3.PipelineServiceRepository;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/services/pipelineServices")
@ -269,10 +269,8 @@ public class PipelineServiceResource extends EntityResource<PipelineService, Pip
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreatePipelineService create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
PipelineService service = getService(create, securityContext);
service = addHref(uriInfo, dao.create(uriInfo, service));
return Response.created(service.getHref()).entity(service).build();
return create(uriInfo, securityContext, service, ADMIN | BOT);
}
@PUT
@ -294,10 +292,7 @@ public class PipelineServiceResource extends EntityResource<PipelineService, Pip
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreatePipelineService update)
throws IOException, ParseException {
PipelineService service = getService(update, securityContext);
SecurityUtil.checkAdminOrBotOrOwner(authorizer, securityContext, dao.getOriginalOwner(service));
PutResponse<PipelineService> response = dao.createOrUpdate(uriInfo, service, true);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, service, ADMIN | BOT | OWNER);
}
@DELETE
@ -321,9 +316,7 @@ public class PipelineServiceResource extends EntityResource<PipelineService, Pip
@Parameter(description = "Id of the pipeline service", schema = @Schema(type = "string")) @PathParam("id")
String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<PipelineService> response = dao.delete(securityContext.getUserPrincipal().getName(), id, recursive);
return response.toResponse();
return delete(uriInfo, securityContext, id, recursive, ADMIN | BOT);
}
private PipelineService getService(CreatePipelineService create, SecurityContext securityContext) {

View File

@ -14,6 +14,9 @@
package org.openmetadata.catalog.resources.services.storage;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
@ -53,12 +56,9 @@ import org.openmetadata.catalog.jdbi3.StorageServiceRepository;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/services/storageServices")
@ -267,10 +267,8 @@ public class StorageServiceResource extends EntityResource<StorageService, Stora
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateStorageService create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
StorageService service = getService(create, securityContext);
service = addHref(uriInfo, dao.create(uriInfo, service));
return Response.created(service.getHref()).entity(service).build();
return create(uriInfo, securityContext, service, ADMIN | BOT);
}
@PUT
@ -290,10 +288,7 @@ public class StorageServiceResource extends EntityResource<StorageService, Stora
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateStorageService update)
throws IOException, ParseException {
StorageService service = getService(update, securityContext);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(service));
PutResponse<StorageService> response = dao.createOrUpdate(uriInfo, service, true);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, service, ADMIN | BOT | OWNER);
}
@DELETE
@ -316,9 +311,7 @@ public class StorageServiceResource extends EntityResource<StorageService, Stora
@Parameter(description = "Id of the storage service", schema = @Schema(type = "string")) @PathParam("id")
String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<StorageService> response = dao.delete(securityContext.getUserPrincipal().getName(), id, recursive);
return response.toResponse();
return delete(uriInfo, securityContext, id, recursive, ADMIN | BOT);
}
private StorageService getService(CreateStorageService create, SecurityContext securityContext) {

View File

@ -13,6 +13,8 @@
package org.openmetadata.catalog.resources.tags;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
import io.swagger.annotations.Api;
@ -284,7 +286,7 @@ public class TagResource {
public Response createCategory(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateTagCategory create)
throws IOException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
TagCategory category =
new TagCategory()
.withName(create.getName())
@ -316,7 +318,7 @@ public class TagResource {
String category,
@Valid CreateTag create)
throws IOException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Tag tag =
new Tag()
.withName(create.getName())
@ -357,7 +359,7 @@ public class TagResource {
String primaryTag,
@Valid CreateTag create)
throws IOException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Tag tag =
new Tag()
.withName(create.getName())
@ -384,7 +386,7 @@ public class TagResource {
String categoryName,
@Valid CreateTagCategory create)
throws IOException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
TagCategory category =
new TagCategory()
.withName(create.getName())
@ -416,7 +418,7 @@ public class TagResource {
String primaryTag,
@Valid CreateTag create)
throws IOException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Tag tag =
new Tag()
.withName(create.getName())
@ -456,7 +458,7 @@ public class TagResource {
String secondaryTag,
@Valid CreateTag create)
throws IOException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
Tag tag =
new Tag()
.withName(create.getName())

View File

@ -13,6 +13,9 @@
package org.openmetadata.catalog.resources.teams;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import io.dropwizard.jersey.PATCH;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
@ -57,13 +60,10 @@ import org.openmetadata.catalog.jdbi3.RoleRepository;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/roles")
@ -291,10 +291,8 @@ public class RoleResource extends EntityResource<Role, RoleRepository> {
public Response create(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateRole createRole)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Role role = getRole(createRole, securityContext);
role = addHref(uriInfo, dao.create(uriInfo, role));
return Response.created(role.getHref()).entity(role).build();
return create(uriInfo, securityContext, role, ADMIN | BOT);
}
@PUT
@ -312,11 +310,8 @@ public class RoleResource extends EntityResource<Role, RoleRepository> {
public Response createOrUpdateRole(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateRole createRole)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Role role = getRole(createRole, securityContext);
RestUtil.PutResponse<Role> response = dao.createOrUpdate(uriInfo, role);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, role, ADMIN | BOT);
}
@PATCH
@ -341,11 +336,7 @@ public class RoleResource extends EntityResource<Role, RoleRepository> {
}))
JsonPatch patch)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
PatchResponse<Role> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE
@ -360,11 +351,9 @@ public class RoleResource extends EntityResource<Role, RoleRepository> {
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
// A role has a strong relationship with a policy. Recursively delete the policy that the role contains, to avoid
// leaving a dangling policy without a role.
DeleteResponse<Role> response = dao.delete(securityContext.getUserPrincipal().getName(), id, true);
return response.toResponse();
return delete(uriInfo, securityContext, id, true, ADMIN | BOT);
}
private Role getRole(CreateRole cr, SecurityContext securityContext) {

View File

@ -13,6 +13,10 @@
package org.openmetadata.catalog.resources.teams;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.dropwizard.jersey.PATCH;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
@ -56,13 +60,8 @@ import org.openmetadata.catalog.jdbi3.TeamRepository;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityInterface;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/teams")
@ -271,10 +270,8 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
})
public Response create(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateTeam ct)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Team team = getTeam(ct, securityContext);
addHref(uriInfo, dao.create(uriInfo, team));
return Response.created(team.getHref()).entity(team).build();
return create(uriInfo, securityContext, team, ADMIN | BOT);
}
@PUT
@ -293,10 +290,7 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateTeam ct)
throws IOException, ParseException {
Team team = getTeam(ct, securityContext);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(team));
RestUtil.PutResponse<Team> response = dao.createOrUpdate(uriInfo, team);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, team, ADMIN | BOT | OWNER);
}
@PATCH
@ -321,14 +315,7 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
}))
JsonPatch patch)
throws IOException, ParseException {
Team team = dao.get(uriInfo, id, getFields(Entity.FIELD_OWNER));
EntityInterface<Team> entityInterface = dao.getEntityInterface(team);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer, securityContext, entityInterface.getEntityReference(), entityInterface.getOwner(), patch);
PatchResponse<Team> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE
@ -343,9 +330,7 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Team> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
private Team getTeam(CreateTeam ct, SecurityContext securityContext) {

View File

@ -13,6 +13,10 @@
package org.openmetadata.catalog.resources.teams;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import io.dropwizard.jersey.PATCH;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
@ -65,8 +69,6 @@ import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.ResultList;
@Slf4j
@ -309,9 +311,10 @@ public class UserResource extends EntityResource<User, UserRepository> {
public Response createUser(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateUser create)
throws IOException, ParseException {
if (create.getIsAdmin() != null && create.getIsAdmin()) {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
if (Boolean.TRUE.equals(create.getIsAdmin())) {
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
}
// TODO do we need to authenticate user is creating himself?
User user = getUser(securityContext, create);
addHref(uriInfo, dao.create(uriInfo, user));
return Response.created(user.getHref()).entity(user).build();
@ -332,12 +335,13 @@ public class UserResource extends EntityResource<User, UserRepository> {
public Response createOrUpdateUser(
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateUser create)
throws IOException, ParseException {
if ((create.getIsAdmin() != null && create.getIsAdmin()) || (create.getIsBot() != null && create.getIsBot())) {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
if (Boolean.TRUE.equals(create.getIsAdmin()) || Boolean.TRUE.equals(create.getIsBot())) {
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
}
// TODO this is different from POST method
User user = getUser(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer, securityContext, new UserEntityInterface(user).getEntityReference());
SecurityUtil.authorize(
authorizer, securityContext, null, new UserEntityInterface(user).getEntityReference(), ADMIN | BOT | OWNER);
RestUtil.PutResponse<User> response = dao.createOrUpdate(uriInfo, user);
addHref(uriInfo, response.getEntity());
return response.toResponse();
@ -370,17 +374,11 @@ public class UserResource extends EntityResource<User, UserRepository> {
if (patchOpObject.containsKey("path") && patchOpObject.containsKey("value")) {
String path = patchOpObject.getString("path");
if (path.equals("/isAdmin") || path.equals("/isBot")) {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
SecurityUtil.authorizeAdmin(authorizer, securityContext, ADMIN | BOT);
}
}
}
User user = dao.get(uriInfo, id, Fields.EMPTY_FIELDS);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer, securityContext, new UserEntityInterface(user).getEntityReference());
PatchResponse<User> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE
@ -395,9 +393,7 @@ public class UserResource extends EntityResource<User, UserRepository> {
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<User> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
private User getUser(SecurityContext securityContext, CreateUser create) throws IOException {

View File

@ -13,7 +13,9 @@
package org.openmetadata.catalog.resources.topics;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.security.SecurityUtil.ADMIN;
import static org.openmetadata.catalog.security.SecurityUtil.BOT;
import static org.openmetadata.catalog.security.SecurityUtil.OWNER;
import com.google.inject.Inject;
import io.swagger.annotations.Api;
@ -59,13 +61,8 @@ import org.openmetadata.catalog.jdbi3.TopicRepository;
import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.resources.EntityResource;
import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.SecurityUtil;
import org.openmetadata.catalog.type.EntityHistory;
import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.RestUtil.DeleteResponse;
import org.openmetadata.catalog.util.RestUtil.PatchResponse;
import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList;
@Path("/v1/topics")
@ -278,11 +275,8 @@ public class TopicResource extends EntityResource<Topic, TopicRepository> {
})
public Response create(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateTopic create)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
Topic topic = getTopic(securityContext, create);
topic = addHref(uriInfo, dao.create(uriInfo, topic));
return Response.created(topic.getHref()).entity(topic).build();
return create(uriInfo, securityContext, topic, ADMIN | BOT);
}
@PATCH
@ -307,19 +301,7 @@ public class TopicResource extends EntityResource<Topic, TopicRepository> {
}))
JsonPatch patch)
throws IOException, ParseException {
Fields fields = getFields(FIELD_OWNER);
Topic topic = dao.get(uriInfo, id, fields);
SecurityUtil.checkAdminRoleOrPermissions(
authorizer,
securityContext,
dao.getEntityInterface(topic).getEntityReference(),
dao.getOwnerReference(topic),
patch);
PatchResponse<Topic> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return patchInternal(uriInfo, securityContext, id, patch);
}
@PUT
@ -337,10 +319,7 @@ public class TopicResource extends EntityResource<Topic, TopicRepository> {
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateTopic create)
throws IOException, ParseException {
Topic topic = getTopic(securityContext, create);
SecurityUtil.checkAdminRoleOrPermissions(authorizer, securityContext, dao.getOriginalOwner(topic));
PutResponse<Topic> response = dao.createOrUpdate(uriInfo, topic);
addHref(uriInfo, response.getEntity());
return response.toResponse();
return createOrUpdate(uriInfo, securityContext, topic, ADMIN | BOT | OWNER);
}
@PUT
@ -395,9 +374,7 @@ public class TopicResource extends EntityResource<Topic, TopicRepository> {
})
public Response delete(@Context UriInfo uriInfo, @Context SecurityContext securityContext, @PathParam("id") String id)
throws IOException, ParseException {
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
DeleteResponse<Topic> response = dao.delete(securityContext.getUserPrincipal().getName(), id);
return response.toResponse();
return delete(uriInfo, securityContext, id, false, ADMIN | BOT);
}
private Topic getTopic(SecurityContext securityContext, CreateTopic create) {

View File

@ -17,16 +17,16 @@ import java.security.Principal;
/** Holds context information of authenticated user, which will be used for authorization. */
public final class AuthenticationContext {
private Principal principal;
private final Principal principal;
public AuthenticationContext(Principal principal) {
this.principal = principal;
}
public Principal getPrincipal() {
return principal;
}
public void setPrincipal(Principal principal) {
this.principal = principal;
}
@Override
public String toString() {
return "AuthenticationContext{" + ", principal=" + principal + '}';

View File

@ -30,53 +30,50 @@ import org.openmetadata.catalog.type.MetadataOperation;
import org.openmetadata.catalog.util.JsonPatchUtils;
public final class SecurityUtil {
public static final int ADMIN = 1;
public static final int BOT = 2;
public static final int OWNER = 4;
public static final int PERMISSIONS = 8;
private SecurityUtil() {}
public static void checkAdminRole(Authorizer authorizer, SecurityContext securityContext) {
Principal principal = securityContext.getUserPrincipal();
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(principal);
if (!authorizer.isAdmin(authenticationCtx)) {
throw new AuthorizationException(notAdmin(principal));
public static void authorizeAdmin(Authorizer authorizer, SecurityContext securityContext, int checkFlags) {
if (checkOwner(checkFlags) || checkPermissions(checkFlags)) {
throw new IllegalArgumentException("Only ADMIN or BOT authorization is allowed");
}
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(securityContext);
if (authorizer.isAdmin(authenticationCtx)) {
return;
}
if (checkBot(checkFlags) && authorizer.isBot(authenticationCtx)) {
return;
}
throw new AuthorizationException(notAdmin(authenticationCtx.getPrincipal()));
}
public static Boolean isAdminOrBotRole(Authorizer authorizer, SecurityContext securityContext) {
try {
checkAdminOrBotRole(authorizer, securityContext);
return true;
} catch (AuthorizationException e) {
return false;
public static void authorize(
Authorizer authorizer,
SecurityContext securityContext,
EntityReference entity,
EntityReference owner,
int checkFlags) {
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(securityContext);
if (authorizer.isAdmin(authenticationCtx)) {
return;
}
}
public static void checkAdminOrBotRole(Authorizer authorizer, SecurityContext securityContext) {
Principal principal = securityContext.getUserPrincipal();
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(principal);
if (!authorizer.isAdmin(authenticationCtx) && !authorizer.isBot(authenticationCtx)) {
throw new AuthorizationException(notAdmin(principal));
if (checkFlags == 0) {
throw new AuthorizationException(notAdmin(authenticationCtx.getPrincipal()));
}
}
public static void checkAdminOrBotOrOwner(
Authorizer authorizer, SecurityContext securityContext, EntityReference ownerReference) {
Principal principal = securityContext.getUserPrincipal();
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(principal);
if (!authorizer.isAdmin(authenticationCtx)
&& !authorizer.isBot(authenticationCtx)
&& !authorizer.isOwner(authenticationCtx, ownerReference)) {
throw new AuthorizationException(noPermission(principal));
if ((checkFlags | BOT) > 0 && authorizer.isBot(authenticationCtx)) {
return;
}
}
public static void checkAdminRoleOrPermissions(
Authorizer authorizer, SecurityContext securityContext, EntityReference entityReference) {
Principal principal = securityContext.getUserPrincipal();
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(principal);
if (!authorizer.isAdmin(authenticationCtx)
&& !authorizer.isBot(authenticationCtx)
&& !authorizer.hasPermissions(authenticationCtx, entityReference)) {
throw new AuthorizationException(noPermission(principal));
if ((checkFlags | OWNER) > 0 && authorizer.isOwner(authenticationCtx, owner)) {
return;
}
if ((checkFlags | PERMISSIONS) > 0 && authorizer.hasPermissions(authenticationCtx, entity)) {
return;
}
throw new AuthorizationException(noPermission(authenticationCtx.getPrincipal()));
}
/** This helper function checks if user has permission to perform the given metadata operation. */
@ -85,15 +82,14 @@ public final class SecurityUtil {
SecurityContext securityContext,
EntityReference entityReference,
MetadataOperation metadataOperation) {
Principal principal = securityContext.getUserPrincipal();
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(principal);
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(securityContext);
if (authorizer.isAdmin(authenticationCtx) || authorizer.isBot(authenticationCtx)) {
return;
}
if (!authorizer.hasPermissions(authenticationCtx, entityReference, metadataOperation)) {
throw new AuthorizationException(noPermission(principal, metadataOperation.value()));
throw new AuthorizationException(noPermission(authenticationCtx.getPrincipal(), metadataOperation.value()));
}
}
@ -108,8 +104,7 @@ public final class SecurityUtil {
EntityReference entityReference,
EntityReference ownerReference,
JsonPatch patch) {
Principal principal = securityContext.getUserPrincipal();
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(principal);
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(securityContext);
if (authorizer.isAdmin(authenticationCtx)
|| authorizer.isBot(authenticationCtx)
@ -121,11 +116,11 @@ public final class SecurityUtil {
// If there are no specific metadata operations that can be determined from the JSON Patch, deny the changes.
if (metadataOperations.isEmpty()) {
throw new AuthorizationException(noPermission(principal));
throw new AuthorizationException(noPermission(authenticationCtx.getPrincipal()));
}
for (MetadataOperation metadataOperation : metadataOperations) {
if (!authorizer.hasPermissions(authenticationCtx, entityReference, metadataOperation)) {
throw new AuthorizationException(noPermission(principal, metadataOperation.value()));
throw new AuthorizationException(noPermission(authenticationCtx.getPrincipal(), metadataOperation.value()));
}
}
}
@ -136,13 +131,7 @@ public final class SecurityUtil {
public static AuthenticationContext getAuthenticationContext(SecurityContext securityContext) {
Principal principal = securityContext.getUserPrincipal();
return SecurityUtil.getAuthenticationContext(principal);
}
private static AuthenticationContext getAuthenticationContext(Principal principal) {
AuthenticationContext context = new AuthenticationContext();
context.setPrincipal(principal);
return context;
return new AuthenticationContext(principal);
}
public static Map<String, String> authHeaders(String username) {
@ -172,4 +161,16 @@ public final class SecurityUtil {
}
return target.request();
}
public static boolean checkBot(int checkFlags) {
return (checkFlags & BOT) > 0;
}
public static boolean checkOwner(int checkFlags) {
return (checkFlags & OWNER) > 0;
}
public static boolean checkPermissions(int checkFlags) {
return (checkFlags & PERMISSIONS) > 0;
}
}

View File

@ -210,10 +210,6 @@ public final class RestUtil {
private final T entity;
private final String changeType;
/**
* Response.Status.CREATED when PUT operation creates a new entity or Response.Status.OK when PUT operation updates
* a new entity
*/
public DeleteResponse(T entity, String changeType) {
this.entity = entity;
this.changeType = changeType;

View File

@ -17,7 +17,7 @@ import static javax.ws.rs.core.Response.Status.FORBIDDEN;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static org.openmetadata.catalog.exception.CatalogExceptionMessage.notAdmin;
import static org.openmetadata.catalog.exception.CatalogExceptionMessage.noPermission;
import static org.openmetadata.catalog.util.TestUtils.ADMIN_AUTH_HEADERS;
import static org.openmetadata.catalog.util.TestUtils.TEST_AUTH_HEADERS;
import static org.openmetadata.catalog.util.TestUtils.TEST_USER_NAME;
@ -166,7 +166,9 @@ public class RoleResourceTest extends EntityResourceTest<Role, CreateRole> {
String originalJson = JsonUtils.pojoToJson(role);
role.setDisplayName("newDisplayName");
assertResponse(
() -> patchEntity(role.getId(), originalJson, role, TEST_AUTH_HEADERS), FORBIDDEN, notAdmin(TEST_USER_NAME));
() -> patchEntity(role.getId(), originalJson, role, TEST_AUTH_HEADERS),
FORBIDDEN,
noPermission(TEST_USER_NAME));
}
private static void validateRole(

View File

@ -156,13 +156,12 @@ public final class TestUtils {
}
public static void post(WebTarget target, Map<String, String> headers) throws HttpResponseException {
Response response = SecurityUtil.addHeaders(target, headers).post(null);
readResponse(response, Status.CREATED.getStatusCode());
post(target, null, headers);
}
public static <K> void post(WebTarget target, K request, Map<String, String> headers) throws HttpResponseException {
Response response =
SecurityUtil.addHeaders(target, headers).post(Entity.entity(request, MediaType.APPLICATION_JSON));
Entity<K> entity = (request == null) ? null : Entity.entity(request, MediaType.APPLICATION_JSON);
Response response = SecurityUtil.addHeaders(target, headers).post(entity);
readResponse(response, Status.CREATED.getStatusCode());
}
@ -215,7 +214,7 @@ public final class TestUtils {
}
public static void assertDeleted(List<EntityReference> list, Boolean expected) {
listOrEmpty(list).forEach(e -> expected.equals(e.getDeleted()));
listOrEmpty(list).forEach(e -> assertEquals(expected, e.getDeleted()));
}
public static void validateEntityReference(EntityReference ref) {