mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-03 06:03:12 +00:00
Fix #3056: Introduce team owner and let them manage their own team; Fix #3516: Authorizer should expect an owner field to be populated before granting permissions. (#3517)
This commit is contained in:
parent
a1941301af
commit
0b30c9f08d
@ -327,7 +327,11 @@ public class ChartResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
Chart chart = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(chart).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(chart).getEntityReference(),
|
||||
dao.getOriginalOwner(chart),
|
||||
patch);
|
||||
|
||||
PatchResponse<Chart> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
|
@ -334,7 +334,11 @@ public class DashboardResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
Dashboard dashboard = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(dashboard).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(dashboard).getEntityReference(),
|
||||
dao.getOwnerReference(dashboard),
|
||||
patch);
|
||||
|
||||
PatchResponse<Dashboard> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
|
@ -341,7 +341,11 @@ public class DatabaseResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
Database database = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(database).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(database).getEntityReference(),
|
||||
dao.getOriginalOwner(database),
|
||||
patch);
|
||||
|
||||
PatchResponse<Database> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
|
@ -364,7 +364,11 @@ public class TableResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
Table table = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(table).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(table).getEntityReference(),
|
||||
dao.getOriginalOwner(table),
|
||||
patch);
|
||||
|
||||
PatchResponse<Table> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
|
@ -331,7 +331,11 @@ public class GlossaryResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
Glossary glossary = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(glossary).getEntityReference(), patch);
|
||||
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());
|
||||
|
@ -368,7 +368,11 @@ public class GlossaryTermResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
GlossaryTerm term = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(term).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(term).getEntityReference(),
|
||||
dao.getOriginalOwner(term),
|
||||
patch);
|
||||
PatchResponse<GlossaryTerm> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
addHref(uriInfo, response.getEntity());
|
||||
|
@ -401,7 +401,11 @@ public class LocationResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
Location location = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(location).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(location).getEntityReference(),
|
||||
dao.getOwnerReference(location),
|
||||
patch);
|
||||
|
||||
PatchResponse<Location> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
|
@ -272,7 +272,11 @@ public class MlModelResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
MlModel mlModel = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(mlModel).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(mlModel).getEntityReference(),
|
||||
dao.getOwnerReference(mlModel),
|
||||
patch);
|
||||
|
||||
PatchResponse<MlModel> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
|
@ -370,7 +370,11 @@ public class AirflowPipelineResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
AirflowPipeline airflowPipeline = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(airflowPipeline).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(airflowPipeline).getEntityReference(),
|
||||
dao.getOriginalOwner(airflowPipeline),
|
||||
patch);
|
||||
|
||||
PatchResponse<AirflowPipeline> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
|
@ -334,7 +334,11 @@ public class PipelineResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
Pipeline pipeline = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(pipeline).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(pipeline).getEntityReference(),
|
||||
dao.getOwnerReference(pipeline),
|
||||
patch);
|
||||
|
||||
PatchResponse<Pipeline> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
|
@ -307,8 +307,8 @@ public class TeamResource {
|
||||
public Response createOrUpdateTeam(
|
||||
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateTeam ct)
|
||||
throws IOException, ParseException {
|
||||
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
|
||||
Team team = getTeam(ct, securityContext);
|
||||
SecurityUtil.checkAdminOrBotOrOwner(authorizer, securityContext, dao.getOriginalOwner(team));
|
||||
RestUtil.PutResponse<Team> response = dao.createOrUpdate(uriInfo, team);
|
||||
addHref(uriInfo, response.getEntity());
|
||||
return response.toResponse();
|
||||
@ -339,7 +339,11 @@ public class TeamResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELDS);
|
||||
Team team = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(team).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(team).getEntityReference(),
|
||||
dao.getOriginalOwner(team),
|
||||
patch);
|
||||
PatchResponse<Team> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
addHref(uriInfo, response.getEntity());
|
||||
@ -370,6 +374,7 @@ public class TeamResource {
|
||||
.withDescription(ct.getDescription())
|
||||
.withDisplayName(ct.getDisplayName())
|
||||
.withProfile(ct.getProfile())
|
||||
.withOwner(ct.getOwner())
|
||||
.withUpdatedBy(securityContext.getUserPrincipal().getName())
|
||||
.withUpdatedAt(System.currentTimeMillis())
|
||||
.withUsers(dao.getEntityReferences(ct.getUsers()))
|
||||
|
@ -332,7 +332,11 @@ public class TopicResource {
|
||||
Fields fields = new Fields(ALLOWED_FIELDS, FIELD_OWNER);
|
||||
Topic topic = dao.get(uriInfo, id, fields);
|
||||
SecurityUtil.checkAdminRoleOrPermissions(
|
||||
authorizer, securityContext, dao.getEntityInterface(topic).getEntityReference(), patch);
|
||||
authorizer,
|
||||
securityContext,
|
||||
dao.getEntityInterface(topic).getEntityReference(),
|
||||
dao.getOwnerReference(topic),
|
||||
patch);
|
||||
|
||||
PatchResponse<Topic> response =
|
||||
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
|
||||
|
@ -127,9 +127,12 @@ public class DefaultAuthorizer implements Authorizer {
|
||||
@Override
|
||||
public boolean hasPermissions(AuthenticationContext ctx, EntityReference owner) {
|
||||
validateAuthenticationContext(ctx);
|
||||
// To encourage users to claim or update changes to tables when a non-owner or un-claimed datasets.
|
||||
// Since we have roles and operations. An Admin could enable updateDescription, tags, ownership permissions to
|
||||
// a role and assign that to the users who can update the entities. With this we can look at the owner as a strict
|
||||
// requirement to manage entities. So if owner is null we will not allow users to update entities. They can get a
|
||||
// role that allows them to update the entity.
|
||||
if (owner == null) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
User user = getUserFromAuthenticationContext(ctx);
|
||||
|
@ -103,11 +103,17 @@ public final class SecurityUtil {
|
||||
* metadata operations that can be derived from JSON patch.
|
||||
*/
|
||||
public static void checkAdminRoleOrPermissions(
|
||||
Authorizer authorizer, SecurityContext securityContext, EntityReference entityReference, JsonPatch patch) {
|
||||
Authorizer authorizer,
|
||||
SecurityContext securityContext,
|
||||
EntityReference entityReference,
|
||||
EntityReference ownerReference,
|
||||
JsonPatch patch) {
|
||||
Principal principal = securityContext.getUserPrincipal();
|
||||
AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(principal);
|
||||
|
||||
if (authorizer.isAdmin(authenticationCtx) || authorizer.isBot(authenticationCtx)) {
|
||||
if (authorizer.isAdmin(authenticationCtx)
|
||||
|| authorizer.isBot(authenticationCtx)
|
||||
|| authorizer.hasPermissions(authenticationCtx, ownerReference)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -29,12 +29,22 @@
|
||||
"default": null
|
||||
},
|
||||
"defaultRoles": {
|
||||
"description": "Roles to be assigned to all users that are part of this team.",
|
||||
"description": "Roles to be assigned to all users that are part of this team.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "../../type/basic.json#/definitions/uuid"
|
||||
},
|
||||
"default": null
|
||||
},
|
||||
"owner": {
|
||||
"description": "Owner of this team. ",
|
||||
"$ref": "../../type/entityReference.json",
|
||||
"default": null
|
||||
},
|
||||
"joinable": {
|
||||
"description": "This field describes if the users can join a team without any permission. By default this is set to True.",
|
||||
"type": "boolean",
|
||||
"default": "true"
|
||||
}
|
||||
},
|
||||
"required": ["name"],
|
||||
|
@ -56,6 +56,11 @@
|
||||
"description": "List of entities owned by the team.",
|
||||
"$ref": "../../type/entityReference.json#/definitions/entityReferenceList"
|
||||
},
|
||||
"owner": {
|
||||
"description": "Owner of this team. ",
|
||||
"$ref": "../../type/entityReference.json",
|
||||
"default": null
|
||||
},
|
||||
"changeDescription": {
|
||||
"description": "Change that lead to this version of the entity.",
|
||||
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
|
||||
|
@ -7,5 +7,5 @@ Provides metadata version information.
|
||||
|
||||
from incremental import Version
|
||||
|
||||
__version__ = Version("metadata", 0, 9, 0, dev=0)
|
||||
__version__ = Version("metadata", 0, 9, 0, dev=1)
|
||||
__all__ = ["__version__"]
|
||||
|
Loading…
x
Reference in New Issue
Block a user