Skip to content

Commit

Permalink
relese: 0.8.3 (#65)
Browse files Browse the repository at this point in the history
### Description

This release fixes an issue (#63) that was causing an error message to
show on-screen for user accounts that don't have AIOPs or Event
Intelligence capabilities.


![image](https://github.com/PagerDuty/backstage-plugin/assets/2689939/020d8654-49c1-43fa-8769-f001195f1b0e)

With this change instead of getting an out-of-context error message,
users will see the following image and message instead.


![image](https://github.com/PagerDuty/backstage-plugin/assets/2689939/5554c2ec-0549-4e40-8d34-b4acecc8e8f5)

## Acknowledgement

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.

**Disclaimer:** We value your time and bandwidth. As such, any pull
requests created on non-triaged issues might not be successful.
  • Loading branch information
t1agob authored Jan 31, 2024
2 parents 0671134 + 13620a6 commit e6baf12
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ dist
dist-types
dist-workspace
assets
!src/assets

# Gatsby files
.cache/
Expand Down
11 changes: 9 additions & 2 deletions src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ import { PagerDutyEntity } from '../types';
/** @public */
export class UnauthorizedError extends Error {}

/** @public */
export class ForbiddenError extends Error { }

/** @public */
export const pagerDutyApiRef = createApiRef<PagerDutyApi>({
id: 'plugin.pagerduty.api',
Expand Down Expand Up @@ -178,11 +181,15 @@ export class PagerDutyClient implements PagerDutyApi {
): Promise<Response> {
const response = await this.config.fetchApi.fetch(url, options);
if (response.status === 401) {
throw new UnauthorizedError();
throw new UnauthorizedError("Unauthorized: You don't have access to this resource");
}

if (response.status === 403) {
throw new ForbiddenError("Forbidden: You are not allowed to perform this action");
}

if (response.status === 404) {
throw new NotFoundError();
throw new NotFoundError("Not Found: Resource not found");
}

if (!response.ok) {
Expand Down
7 changes: 6 additions & 1 deletion src/assets/emptystate.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions src/assets/forbiddenstate.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions src/components/ChangeEvents/ChangeEventForbiddenState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2020 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.
*/

// eslint-disable-next-line @backstage/no-undeclared-imports
import React from 'react';
import { Grid, Typography } from '@material-ui/core';
import ForbiddenStateImage from '../../assets/forbiddenstate.svg';

export const ChangeEventForbiddenState = () => {
return (
<Grid container justify="center" direction="column" alignItems="center">
<Grid item xs={12}>
<Typography variant="h5">Feature not available with your account or token.</Typography>
</Grid>
<Grid item xs={12}>
<img
src={ForbiddenStateImage}
alt="ForbiddenState"
data-testid="forbiddenStateImg"
/>
</Grid>
</Grid>
);
};
18 changes: 18 additions & 0 deletions src/components/ChangeEvents/ChangeEvents.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,24 @@ describe('Incidents', () => {
expect(getByText('No change events to display yet.')).toBeInTheDocument();
});

it("Renders a forbidden state when change events is undefined", async () => {
mockPagerDutyApi.getChangeEventsByServiceId = jest
.fn()
.mockImplementationOnce(async () => {throw new Error("Forbidden: You allowed to perform this action");});

const { getByText, queryByTestId } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<ChangeEvents serviceId="abc" refreshEvents={false} />
</ApiProvider>
)
);
await waitFor(() => !queryByTestId("progress"));
expect(
getByText("Feature not available with your account or token.")
).toBeInTheDocument();
});

it('Renders all change events', async () => {
mockPagerDutyApi.getChangeEventsByServiceId = jest
.fn()
Expand Down
5 changes: 5 additions & 0 deletions src/components/ChangeEvents/ChangeEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import React, { useEffect } from 'react';
import { List } from '@material-ui/core';
import { ChangeEventListItem } from './ChangeEventListItem';
import { ChangeEventEmptyState } from './ChangeEventEmptyState';
import { ChangeEventForbiddenState } from './ChangeEventForbiddenState';
import useAsyncFn from 'react-use/lib/useAsyncFn';
import { pagerDutyApiRef } from '../../api';
import { useApi } from '@backstage/core-plugin-api';
Expand All @@ -45,6 +46,10 @@ export const ChangeEvents = ({ serviceId, refreshEvents }: Props) => {
}, [refreshEvents, getChangeEvents]);

if (error) {
if (error.message.includes('Forbidden')) {
return <ChangeEventForbiddenState />;
}

return (
<Alert severity="error">
Error encountered while fetching information. {error.message}
Expand Down

0 comments on commit e6baf12

Please sign in to comment.