123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- import {useCallback, useState} from 'react';
- import omit from 'lodash/omit';
- import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
- import {openModal} from 'sentry/actionCreators/modal';
- import {Button} from 'sentry/components/button';
- import ExternalLink from 'sentry/components/links/externalLink';
- import LoadingError from 'sentry/components/loadingError';
- import LoadingIndicator from 'sentry/components/loadingIndicator';
- import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
- import {IconAdd} from 'sentry/icons';
- import {t, tct} from 'sentry/locale';
- import type {Organization} from 'sentry/types/organization';
- import type {Relay, RelayActivity} from 'sentry/types/relay';
- import {useApiQuery} from 'sentry/utils/queryClient';
- import useApi from 'sentry/utils/useApi';
- import useOrganization from 'sentry/utils/useOrganization';
- import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
- import TextBlock from 'sentry/views/settings/components/text/textBlock';
- import PermissionAlert from 'sentry/views/settings/organization/permissionAlert';
- import Add from './modals/add';
- import Edit from './modals/edit';
- import EmptyState from './emptyState';
- import List from './list';
- const RELAY_DOCS_LINK = 'https://getsentry.github.io/relay/';
- export function RelayWrapper() {
- const organization = useOrganization();
- const api = useApi();
- const [relays, setRelays] = useState<Relay[]>(organization.trustedRelays);
- const disabled = !organization.access.includes('org:write');
- const handleOpenAddDialog = useCallback(() => {
- openModal(modalProps => (
- <Add
- {...modalProps}
- savedRelays={relays}
- api={api}
- orgSlug={organization.slug}
- onSubmitSuccess={response => {
- addSuccessMessage(t('Successfully added Relay public key'));
- setRelays(response.trustedRelays);
- }}
- />
- ));
- }, [relays, api, organization.slug]);
- return (
- <SentryDocumentTitle title={t('Relay')}>
- <SettingsPageHeader
- title={t('Relay')}
- action={
- <Button
- title={
- disabled ? t('You do not have permission to register keys') : undefined
- }
- priority="primary"
- size="sm"
- icon={<IconAdd isCircled />}
- onClick={handleOpenAddDialog}
- disabled={disabled}
- >
- {t('Register Key')}
- </Button>
- }
- />
- <PermissionAlert />
- <TextBlock>
- {tct(
- 'Sentry Relay offers enterprise-grade data security by providing a standalone service that acts as a middle layer between your application and sentry.io. Go to [link:Relay Documentation] for setup and details.',
- {link: <ExternalLink href={RELAY_DOCS_LINK} />}
- )}
- </TextBlock>
- {relays.length === 0 ? (
- <EmptyState />
- ) : (
- <RelayUsageList
- orgSlug={organization.slug}
- disabled={disabled}
- relays={relays}
- api={api}
- onRelaysChange={setRelays}
- />
- )}
- </SentryDocumentTitle>
- );
- }
- function RelayUsageList({
- relays,
- orgSlug,
- disabled,
- api,
- onRelaysChange,
- }: {
- api: ReturnType<typeof useApi>;
- disabled: boolean;
- onRelaysChange: (relays: Relay[]) => void;
- orgSlug: Organization['slug'];
- relays: Relay[];
- }) {
- const {isPending, isError, refetch, data} = useApiQuery<RelayActivity[]>(
- [`/organizations/${orgSlug}/relay_usage/`],
- {
- staleTime: 0,
- retry: false,
- enabled: relays.length > 0,
- }
- );
- const handleOpenEditDialog = useCallback(
- (publicKey: string) => {
- const editRelay = relays.find(relay => relay.publicKey === publicKey);
- if (!editRelay) {
- return;
- }
- openModal(modalProps => (
- <Edit
- {...modalProps}
- savedRelays={relays}
- api={api}
- orgSlug={orgSlug}
- relay={editRelay}
- onSubmitSuccess={response => {
- addSuccessMessage(t('Successfully updated Relay public key'));
- onRelaysChange(response.trustedRelays);
- }}
- />
- ));
- },
- [orgSlug, relays, api, onRelaysChange]
- );
- const handleDeleteRelay = useCallback(
- async (publicKey: string) => {
- const trustedRelays = relays
- .filter(relay => relay.publicKey !== publicKey)
- .map(relay => omit(relay, ['created', 'lastModified']));
- try {
- const response = await api.requestPromise(`/organizations/${orgSlug}/`, {
- method: 'PUT',
- data: {trustedRelays},
- });
- addSuccessMessage(t('Successfully deleted Relay public key'));
- onRelaysChange(response.trustedRelays);
- } catch {
- addErrorMessage(t('An unknown error occurred while deleting Relay public key'));
- }
- },
- [relays, api, orgSlug, onRelaysChange]
- );
- if (isPending) {
- return <LoadingIndicator />;
- }
- if (isError) {
- return <LoadingError onRetry={refetch} />;
- }
- return (
- <List
- relays={relays}
- relayActivities={data}
- disabled={disabled}
- onEdit={publicKey => () => handleOpenEditDialog(publicKey)}
- onRefresh={() => refetch()}
- onDelete={publicKey => () => handleDeleteRelay(publicKey)}
- />
- );
- }
|