keySettings.tsx 6.0 KB

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