permissio framework add to azure-devops

Signed-off-by: Deepankumar Loganathan <deepan0433@gmail.com>
This commit is contained in:
Deepankumar Loganathan
2024-01-29 07:29:02 +01:00
parent a35225da19
commit b433e52d5f
14 changed files with 119 additions and 9 deletions
+5 -1
View File
@@ -36,5 +36,9 @@
},
"files": [
"dist"
]
],
"dependencies": {
"@backstage/plugin-catalog-common": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^"
}
}
@@ -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,
@@ -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}`;
@@ -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 (
<EmptyState
missing="data"
title="No Buils to show"
description="You are not authorized!"
/>
);
}
return (
<div>
<ResponseErrorPanel error={error} />
@@ -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 (
<EmptyState
missing="data"
title="No Tags to show"
description="You are not authorized!"
/>
);
}
return <ResponseErrorPanel error={error} />;
}
@@ -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 (
<EmptyState
missing="data"
title="No Pull Requests to show"
description="You are not authorized!"
/>
);
}
return <ResponseErrorPanel error={error} />;
}
@@ -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 (
<EmptyState
missing="data"
title="No Pull Requests to show"
description="You are not authorized!"
/>
);
}
return <ResponseErrorPanel error={error} />;
}
@@ -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 (
<EmptyState
title="No README available for this entity"
missing="field"
description="You are not authorized!"
/>
);
} else if (isNotFoundError(error)) {
return (
<EmptyState
title="No README available for this entity"
@@ -80,6 +89,7 @@ const ReadmeCardError = ({ error }: ErrorProps) => {
}
/>
);
}
return <ErrorPanel title={error.message} error={error} />;
};
+10 -2
View File
@@ -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 {
+8 -2
View File
@@ -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 {
@@ -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 {
+3 -1
View File
@@ -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,
+1
View File
@@ -18,3 +18,4 @@ export * from './arrayHas';
export * from './equalsIgnoreCase';
export * from './getDurationFromDates';
export * from './getAnnotationValuesFromEntity';
export * from './validateError';
@@ -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;
}