keySettings.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import {Fragment, useCallback} from 'react';
  2. import {
  3. addErrorMessage,
  4. addLoadingMessage,
  5. addSuccessMessage,
  6. } from 'sentry/actionCreators/indicator';
  7. import Access from 'sentry/components/acl/access';
  8. import {Button} from 'sentry/components/button';
  9. import Confirm from 'sentry/components/confirm';
  10. import DateTime from 'sentry/components/dateTime';
  11. import FieldGroup from 'sentry/components/forms/fieldGroup';
  12. import BooleanField from 'sentry/components/forms/fields/booleanField';
  13. import TextField from 'sentry/components/forms/fields/textField';
  14. import Form from 'sentry/components/forms/form';
  15. import {Panel, PanelAlert, PanelBody, PanelHeader} from 'sentry/components/panels';
  16. import {t} from 'sentry/locale';
  17. import {Organization, Project} from 'sentry/types';
  18. import useApi from 'sentry/utils/useApi';
  19. import KeyRateLimitsForm from 'sentry/views/settings/project/projectKeys/details/keyRateLimitsForm';
  20. import {LoaderSettings} from 'sentry/views/settings/project/projectKeys/details/loaderSettings';
  21. import ProjectKeyCredentials from 'sentry/views/settings/project/projectKeys/projectKeyCredentials';
  22. import {ProjectKey} from 'sentry/views/settings/project/projectKeys/types';
  23. type Props = {
  24. data: ProjectKey;
  25. onRemove: () => void;
  26. organization: Organization;
  27. params: {
  28. keyId: string;
  29. projectId: string;
  30. };
  31. project: Project;
  32. };
  33. export function KeySettings({onRemove, organization, project, params, data}: Props) {
  34. const api = useApi();
  35. const {keyId, projectId} = params;
  36. const apiEndpoint = `/projects/${organization.slug}/${projectId}/keys/${keyId}/`;
  37. const handleRemove = useCallback(async () => {
  38. addLoadingMessage(t('Revoking key\u2026'));
  39. try {
  40. await api.requestPromise(
  41. `/projects/${organization.slug}/${projectId}/keys/${keyId}/`,
  42. {
  43. method: 'DELETE',
  44. }
  45. );
  46. onRemove();
  47. addSuccessMessage(t('Revoked key'));
  48. } catch (_err) {
  49. addErrorMessage(t('Unable to revoke key'));
  50. }
  51. }, [organization, api, onRemove, keyId, projectId]);
  52. return (
  53. <Fragment>
  54. <Access access={['project:write']} project={project}>
  55. {({hasAccess}) => (
  56. <Fragment>
  57. <Form
  58. saveOnBlur
  59. allowUndo
  60. apiEndpoint={apiEndpoint}
  61. apiMethod="PUT"
  62. initialData={data}
  63. >
  64. <Panel>
  65. <PanelHeader>{t('Details')}</PanelHeader>
  66. <PanelBody>
  67. <TextField
  68. name="name"
  69. label={t('Name')}
  70. disabled={!hasAccess}
  71. required={false}
  72. maxLength={64}
  73. />
  74. <BooleanField
  75. name="isActive"
  76. label={t('Enabled')}
  77. required={false}
  78. disabled={!hasAccess}
  79. help="Accept events from this key? This may be used to temporarily suspend a key."
  80. />
  81. <FieldGroup label={t('Created')}>
  82. <div className="controls">
  83. <DateTime date={data.dateCreated} />
  84. </div>
  85. </FieldGroup>
  86. </PanelBody>
  87. </Panel>
  88. </Form>
  89. <KeyRateLimitsForm
  90. organization={organization}
  91. params={params}
  92. data={data}
  93. disabled={!hasAccess}
  94. />
  95. <Panel>
  96. <PanelHeader>{t('JavaScript Loader Script')}</PanelHeader>
  97. <PanelBody>
  98. <PanelAlert type="info" showIcon>
  99. {t(
  100. 'Note that it can take a few minutes until changed options are live.'
  101. )}
  102. </PanelAlert>
  103. <LoaderSettings
  104. orgSlug={organization.slug}
  105. keyId={params.keyId}
  106. project={project}
  107. projectKey={data}
  108. />
  109. </PanelBody>
  110. </Panel>
  111. <Panel>
  112. <PanelHeader>{t('Credentials')}</PanelHeader>
  113. <PanelBody>
  114. <PanelAlert type="info" showIcon>
  115. {t(
  116. 'Your credentials are coupled to a public and secret key. Different clients will require different credentials, so make sure you check the documentation before plugging things in.'
  117. )}
  118. </PanelAlert>
  119. <ProjectKeyCredentials
  120. projectId={`${data.projectId}`}
  121. data={data}
  122. showPublicKey
  123. showSecretKey
  124. showProjectId
  125. />
  126. </PanelBody>
  127. </Panel>
  128. </Fragment>
  129. )}
  130. </Access>
  131. <Access access={['project:admin']} project={project}>
  132. {({hasAccess}) => (
  133. <Panel>
  134. <PanelHeader>{t('Revoke Key')}</PanelHeader>
  135. <PanelBody>
  136. <FieldGroup
  137. label={t('Revoke Key')}
  138. help={t(
  139. 'Revoking this key will immediately remove and suspend the credentials. This action is irreversible.'
  140. )}
  141. >
  142. <div>
  143. <Confirm
  144. priority="danger"
  145. message={t(
  146. 'Are you sure you want to revoke this key? This will immediately remove and suspend the credentials.'
  147. )}
  148. onConfirm={handleRemove}
  149. confirmText={t('Revoke Key')}
  150. disableConfirmButton={!hasAccess}
  151. >
  152. <Button priority="danger">{t('Revoke Key')}</Button>
  153. </Confirm>
  154. </div>
  155. </FieldGroup>
  156. </PanelBody>
  157. </Panel>
  158. )}
  159. </Access>
  160. </Fragment>
  161. );
  162. }