From b433e52d5f74adf096755f5b40c6544ab38bad52 Mon Sep 17 00:00:00 2001 From: Deepankumar Loganathan Date: Mon, 29 Jan 2024 07:29:02 +0100 Subject: [PATCH] permissio framework add to azure-devops Signed-off-by: Deepankumar Loganathan --- plugins/azure-devops-common/package.json | 6 +++++- plugins/azure-devops/src/api/AzureDevOpsApi.ts | 3 +++ .../azure-devops/src/api/AzureDevOpsClient.ts | 6 ++++++ .../src/components/BuildTable/BuildTable.tsx | 11 +++++++++++ .../src/components/GitTagTable/GitTagTable.tsx | 11 +++++++++++ .../PullRequestTable/PullRequestTable.tsx | 11 +++++++++++ .../PullRequestsPage/PullRequestsPage.tsx | 11 +++++++++++ .../src/components/ReadmeCard/ReadmeCard.tsx | 12 +++++++++++- plugins/azure-devops/src/hooks/useBuildRuns.ts | 12 ++++++++++-- plugins/azure-devops/src/hooks/useGitTags.ts | 10 ++++++++-- .../azure-devops/src/hooks/usePullRequests.ts | 12 ++++++++++-- plugins/azure-devops/src/hooks/useReadme.ts | 4 +++- plugins/azure-devops/src/utils/index.ts | 1 + .../azure-devops/src/utils/validateError.ts | 18 ++++++++++++++++++ 14 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 plugins/azure-devops/src/utils/validateError.ts diff --git a/plugins/azure-devops-common/package.json b/plugins/azure-devops-common/package.json index 23a575f95e..70b7be4964 100644 --- a/plugins/azure-devops-common/package.json +++ b/plugins/azure-devops-common/package.json @@ -36,5 +36,9 @@ }, "files": [ "dist" - ] + ], + "dependencies": { + "@backstage/plugin-catalog-common": "workspace:^", + "@backstage/plugin-permission-common": "workspace:^" + } } diff --git a/plugins/azure-devops/src/api/AzureDevOpsApi.ts b/plugins/azure-devops/src/api/AzureDevOpsApi.ts index 89aa4b7d6e..6dd6eeae6b 100644 --- a/plugins/azure-devops/src/api/AzureDevOpsApi.ts +++ b/plugins/azure-devops/src/api/AzureDevOpsApi.ts @@ -48,6 +48,7 @@ export interface AzureDevOpsApi { getGitTags( projectName: string, repoName: string, + entityRef: string, host?: string, org?: string, ): Promise<{ items: GitTag[] }>; @@ -55,6 +56,7 @@ export interface AzureDevOpsApi { getPullRequests( projectName: string, repoName: string, + entityRef: string, host?: string, org?: string, options?: PullRequestOptions, @@ -70,6 +72,7 @@ export interface AzureDevOpsApi { getBuildRuns( projectName: string, + entityRef: string, repoName?: string, definitionName?: string, host?: string, diff --git a/plugins/azure-devops/src/api/AzureDevOpsClient.ts b/plugins/azure-devops/src/api/AzureDevOpsClient.ts index f5c046ef07..257b1cd014 100644 --- a/plugins/azure-devops/src/api/AzureDevOpsClient.ts +++ b/plugins/azure-devops/src/api/AzureDevOpsClient.ts @@ -71,6 +71,7 @@ export class AzureDevOpsClient implements AzureDevOpsApi { public async getGitTags( projectName: string, + entityRef: string, repoName: string, host?: string, org?: string, @@ -82,6 +83,7 @@ export class AzureDevOpsClient implements AzureDevOpsApi { if (org) { queryString.append('org', org); } + queryString.append('entityRef', entityRef); const urlSegment = `git-tags/${encodeURIComponent( projectName, )}/${encodeURIComponent(repoName)}?${queryString}`; @@ -93,6 +95,7 @@ export class AzureDevOpsClient implements AzureDevOpsApi { public async getPullRequests( projectName: string, repoName: string, + entityRef: string, host?: string, org?: string, options?: PullRequestOptions, @@ -110,6 +113,7 @@ export class AzureDevOpsClient implements AzureDevOpsApi { if (org) { queryString.append('org', org); } + queryString.append('entityRef', entityRef); const urlSegment = `pull-requests/${encodeURIComponent( projectName, )}/${encodeURIComponent(repoName)}?${queryString}`; @@ -136,6 +140,7 @@ export class AzureDevOpsClient implements AzureDevOpsApi { public async getBuildRuns( projectName: string, + entityRef: string, repoName?: string, definitionName?: string, host?: string, @@ -174,6 +179,7 @@ export class AzureDevOpsClient implements AzureDevOpsApi { if (options?.top) { queryString.append('top', options.top.toString()); } + queryString.append('entityRef', entityRef); const urlSegment = `builds/${encodeURIComponent( projectName, )}?${queryString}`; diff --git a/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx b/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx index 09eba5f5a2..bc69b68d56 100644 --- a/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx +++ b/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx @@ -32,12 +32,14 @@ import { StatusWarning, Table, TableColumn, + EmptyState, } from '@backstage/core-components'; import { AzurePipelinesIcon } from '../AzurePipelinesIcon'; import { DateTime } from 'luxon'; import React from 'react'; import { getDurationFromDates } from '../../utils/getDurationFromDates'; +import { isAuthorizationError } from '../../utils'; export const getBuildResultComponent = (result: number | undefined) => { switch (result) { @@ -179,6 +181,15 @@ type BuildTableProps = { export const BuildTable = ({ items, loading, error }: BuildTableProps) => { if (error) { + if (isAuthorizationError(error)) { + return ( + + ); + } return (
diff --git a/plugins/azure-devops/src/components/GitTagTable/GitTagTable.tsx b/plugins/azure-devops/src/components/GitTagTable/GitTagTable.tsx index f34a1929fe..31475a66d7 100644 --- a/plugins/azure-devops/src/components/GitTagTable/GitTagTable.tsx +++ b/plugins/azure-devops/src/components/GitTagTable/GitTagTable.tsx @@ -20,6 +20,7 @@ import { ResponseErrorPanel, Table, TableColumn, + EmptyState, } from '@backstage/core-components'; import { GitTag } from '@backstage/plugin-azure-devops-common'; import React from 'react'; @@ -27,6 +28,7 @@ import React from 'react'; import { AzureGitTagsIcon } from '../AzureGitTagsIcon'; import { useEntity } from '@backstage/plugin-catalog-react'; import { useGitTags } from '../../hooks/useGitTags'; +import { isAuthorizationError } from '../../utils'; const columns: TableColumn[] = [ { @@ -64,6 +66,15 @@ export const GitTagTable = () => { const { items, loading, error } = useGitTags(entity); if (error) { + if (isAuthorizationError(error)) { + return ( + + ); + } return ; } diff --git a/plugins/azure-devops/src/components/PullRequestTable/PullRequestTable.tsx b/plugins/azure-devops/src/components/PullRequestTable/PullRequestTable.tsx index d672102945..3e41a8c46f 100644 --- a/plugins/azure-devops/src/components/PullRequestTable/PullRequestTable.tsx +++ b/plugins/azure-devops/src/components/PullRequestTable/PullRequestTable.tsx @@ -21,6 +21,7 @@ import { ResponseErrorPanel, Table, TableColumn, + EmptyState, } from '@backstage/core-components'; import { PullRequest, @@ -33,6 +34,7 @@ import { DateTime } from 'luxon'; import { PullRequestStatusButtonGroup } from '../PullRequestStatusButtonGroup'; import { useEntity } from '@backstage/plugin-catalog-react'; import { usePullRequests } from '../../hooks/usePullRequests'; +import { isAuthorizationError } from '../../utils'; const columns: TableColumn[] = [ { @@ -104,6 +106,15 @@ export const PullRequestTable = ({ defaultLimit }: PullRequestTableProps) => { ); if (error) { + if (isAuthorizationError(error)) { + return ( + + ); + } return ; } diff --git a/plugins/azure-devops/src/components/PullRequestsPage/PullRequestsPage.tsx b/plugins/azure-devops/src/components/PullRequestsPage/PullRequestsPage.tsx index c5da207bd6..9561c76a2c 100644 --- a/plugins/azure-devops/src/components/PullRequestsPage/PullRequestsPage.tsx +++ b/plugins/azure-devops/src/components/PullRequestsPage/PullRequestsPage.tsx @@ -16,6 +16,7 @@ import { Content, + EmptyState, Header, Page, Progress, @@ -28,6 +29,7 @@ import { FilterType } from './lib/filters'; import { PullRequestGrid } from './lib/PullRequestGrid'; import { useDashboardPullRequests } from '../../hooks'; import { useFilterProcessor } from './lib/hooks'; +import { isAuthorizationError } from '../../utils'; type PullRequestsPageContentProps = { pullRequestGroups: PullRequestGroup[] | undefined; @@ -45,6 +47,15 @@ const PullRequestsPageContent = ({ } if (error) { + if (isAuthorizationError(error)) { + return ( + + ); + } return ; } diff --git a/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx b/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx index 300c9e0d7c..a45c6fe831 100644 --- a/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx +++ b/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx @@ -28,6 +28,7 @@ import { useEntity } from '@backstage/plugin-catalog-react'; import React from 'react'; import { useReadme } from '../../hooks'; +import { isAuthorizationError } from '../../utils'; const useStyles = makeStyles(theme => ({ readMe: { @@ -63,7 +64,15 @@ function isNotFoundError(error: any): boolean { } const ReadmeCardError = ({ error }: ErrorProps) => { - if (isNotFoundError(error)) + if (isAuthorizationError(error)) { + return ( + + ); + } else if (isNotFoundError(error)) { return ( { } /> ); + } return ; }; diff --git a/plugins/azure-devops/src/hooks/useBuildRuns.ts b/plugins/azure-devops/src/hooks/useBuildRuns.ts index e335d2ffaf..21f4d60430 100644 --- a/plugins/azure-devops/src/hooks/useBuildRuns.ts +++ b/plugins/azure-devops/src/hooks/useBuildRuns.ts @@ -24,7 +24,7 @@ import { azureDevOpsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; import { getAnnotationValuesFromEntity } from '../utils'; -import { Entity } from '@backstage/catalog-model'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; export function useBuildRuns( entity: Entity, @@ -44,7 +44,15 @@ export function useBuildRuns( const { value, loading, error } = useAsync(() => { const { project, repo, definition, host, org } = getAnnotationValuesFromEntity(entity); - return api.getBuildRuns(project, repo, definition, host, org, options); + return api.getBuildRuns( + project, + stringifyEntityRef(entity), + repo, + definition, + host, + org, + options, + ); }, [api]); return { diff --git a/plugins/azure-devops/src/hooks/useGitTags.ts b/plugins/azure-devops/src/hooks/useGitTags.ts index 57489316da..3cd65dad92 100644 --- a/plugins/azure-devops/src/hooks/useGitTags.ts +++ b/plugins/azure-devops/src/hooks/useGitTags.ts @@ -16,7 +16,7 @@ import { GitTag } from '@backstage/plugin-azure-devops-common'; -import { Entity } from '@backstage/catalog-model'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { azureDevOpsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; @@ -31,7 +31,13 @@ export function useGitTags(entity: Entity): { const { value, loading, error } = useAsync(() => { const { project, repo, host, org } = getAnnotationValuesFromEntity(entity); - return api.getGitTags(project, repo as string, host, org); + return api.getGitTags( + project, + repo as string, + stringifyEntityRef(entity), + host, + org, + ); }, [api]); return { diff --git a/plugins/azure-devops/src/hooks/usePullRequests.ts b/plugins/azure-devops/src/hooks/usePullRequests.ts index af2c4b1cc1..7347f66156 100644 --- a/plugins/azure-devops/src/hooks/usePullRequests.ts +++ b/plugins/azure-devops/src/hooks/usePullRequests.ts @@ -21,7 +21,7 @@ import { PullRequestStatus, } from '@backstage/plugin-azure-devops-common'; -import { Entity } from '@backstage/catalog-model'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { azureDevOpsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; @@ -47,7 +47,15 @@ export function usePullRequests( const { value, loading, error } = useAsync(() => { const { project, repo, host, org } = getAnnotationValuesFromEntity(entity); - return api.getPullRequests(project, repo as string, host, org, options); + const entityRef = stringifyEntityRef(entity); + return api.getPullRequests( + project, + repo as string, + entityRef, + host, + org, + options, + ); }, [api, top, status]); return { diff --git a/plugins/azure-devops/src/hooks/useReadme.ts b/plugins/azure-devops/src/hooks/useReadme.ts index 9aa376e0bd..cfc7f04bf4 100644 --- a/plugins/azure-devops/src/hooks/useReadme.ts +++ b/plugins/azure-devops/src/hooks/useReadme.ts @@ -16,7 +16,7 @@ import { Readme } from '@backstage/plugin-azure-devops-common'; -import { Entity } from '@backstage/catalog-model'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { azureDevOpsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; @@ -32,9 +32,11 @@ export function useReadme(entity: Entity): { const { value, loading, error } = useAsync(() => { const { project, repo, host, org, readmePath } = getAnnotationValuesFromEntity(entity); + const entityRef = stringifyEntityRef(entity); return api.getReadme({ project, repo: repo as string, + entityRef, host, org, path: readmePath, diff --git a/plugins/azure-devops/src/utils/index.ts b/plugins/azure-devops/src/utils/index.ts index 998bb0e23d..a05ea4f650 100644 --- a/plugins/azure-devops/src/utils/index.ts +++ b/plugins/azure-devops/src/utils/index.ts @@ -18,3 +18,4 @@ export * from './arrayHas'; export * from './equalsIgnoreCase'; export * from './getDurationFromDates'; export * from './getAnnotationValuesFromEntity'; +export * from './validateError'; diff --git a/plugins/azure-devops/src/utils/validateError.ts b/plugins/azure-devops/src/utils/validateError.ts new file mode 100644 index 0000000000..fca1687013 --- /dev/null +++ b/plugins/azure-devops/src/utils/validateError.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2024 The Backstage Authors + * + * 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. + */ +export function isAuthorizationError(error: any): boolean { + return error?.response?.status === 403; +}