Consider group memberships in the OwnershipCard

This commit is contained in:
Dominik Henneke
2020-12-08 18:55:17 +01:00
parent 9a2a925716
commit 2b71db2116
4 changed files with 107 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-org': patch
---
Support transitive ownerships of users and groups.
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { InfoCard, useApi, Progress } from '@backstage/core';
import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model';
import { Entity } from '@backstage/catalog-model';
import { catalogApiRef } from '@backstage/plugin-catalog';
import { useAsync } from 'react-use';
import Alert from '@material-ui/lab/Alert';
@@ -28,6 +29,7 @@ import {
Typography,
} from '@material-ui/core';
import { pageTheme } from '@backstage/theme';
import { isOwnerOf } from '../../isOwnerOf';
type EntitiesKinds = 'Component' | 'API';
type EntitiesTypes =
@@ -118,9 +120,6 @@ export const OwnershipCard = ({
entity: Entity;
variant: string;
}) => {
const {
metadata: { name: groupName },
} = entity;
const catalogApi = useApi(catalogApiRef);
const {
loading,
@@ -129,10 +128,8 @@ export const OwnershipCard = ({
} = useAsync(async () => {
const entitiesList = await catalogApi.getEntities();
const ownedEntitiesList = entitiesList.items.filter(component =>
component?.relations?.some(
r => r.type === RELATION_OWNED_BY && r.target.name === groupName,
),
) as Array<Entity>;
isOwnerOf(entity, component),
);
return [
{
@@ -0,0 +1,42 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Entity, EntityName } from '@backstage/catalog-model';
// TODO: this file is copied from /packages/app/catalog/src/components/getEntityRelations.ts and
// should be replaced once common relation-functions are introduced.
/**
* Get the related entity references.
*/
export function getEntityRelations(
entity: Entity | undefined,
relationType: string,
filter?: { kind: string },
): EntityName[] {
let entityNames =
entity?.relations
?.filter(r => r.type === relationType)
?.map(r => r.target) || [];
if (filter?.kind) {
entityNames = entityNames?.filter(
e => e.kind.toLowerCase() === filter.kind.toLowerCase(),
);
}
return entityNames;
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
Entity,
EntityName,
getEntityName,
RELATION_MEMBER_OF,
RELATION_OWNED_BY,
} from '@backstage/catalog-model';
import { getEntityRelations } from './getEntityRelations';
// TODO: this file is copied from /packages/app/catalog/src/components/isOwnerOf.ts and
// should be replaced once common relation-functions are introduced.
/**
* Check if one entity is owned by another. Returns true, if the entity is owned by the
* owner directly, or if the entity is owned by a group that the owner is a member of.
*/
export function isOwnerOf(owner: Entity, owned: Entity) {
const possibleOwners: EntityName[] = [
...getEntityRelations(owner, RELATION_MEMBER_OF, { kind: 'group' }),
...(owner ? [getEntityName(owner)] : []),
];
const owners = getEntityRelations(owned, RELATION_OWNED_BY);
for (const owner of owners) {
if (
possibleOwners.find(
o =>
owner.kind.toLowerCase() === o.kind.toLowerCase() &&
owner.namespace.toLowerCase() === o.namespace.toLowerCase() &&
owner.name.toLowerCase() === o.name.toLowerCase(),
) !== undefined
) {
return true;
}
}
return false;
}