keySettings.tsx 5.9 KB

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