ServiceAccountPage.tsx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import React, { useEffect, useState } from 'react';
  2. import { connect, ConnectedProps } from 'react-redux';
  3. import { getTimeZone, NavModel } from '@grafana/data';
  4. import { Button } from '@grafana/ui';
  5. import Page from 'app/core/components/Page/Page';
  6. import { contextSrv } from 'app/core/core';
  7. import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
  8. import { getNavModel } from 'app/core/selectors/navModel';
  9. import { StoreState, ServiceAccountDTO, ApiKey, Role, AccessControlAction } from 'app/types';
  10. import { CreateTokenModal, ServiceAccountToken } from './CreateServiceAccountTokenModal';
  11. import { ServiceAccountProfile } from './ServiceAccountProfile';
  12. import { ServiceAccountTokensTable } from './ServiceAccountTokensTable';
  13. import {
  14. deleteServiceAccountToken,
  15. loadServiceAccount,
  16. loadServiceAccountTokens,
  17. createServiceAccountToken,
  18. fetchACOptions,
  19. updateServiceAccount,
  20. deleteServiceAccount,
  21. } from './state/actions';
  22. interface OwnProps extends GrafanaRouteComponentProps<{ id: string }> {
  23. navModel: NavModel;
  24. serviceAccount?: ServiceAccountDTO;
  25. tokens: ApiKey[];
  26. isLoading: boolean;
  27. roleOptions: Role[];
  28. builtInRoles: Record<string, Role[]>;
  29. }
  30. function mapStateToProps(state: StoreState) {
  31. return {
  32. navModel: getNavModel(state.navIndex, 'serviceaccounts'),
  33. serviceAccount: state.serviceAccountProfile.serviceAccount,
  34. tokens: state.serviceAccountProfile.tokens,
  35. isLoading: state.serviceAccountProfile.isLoading,
  36. roleOptions: state.serviceAccounts.roleOptions,
  37. builtInRoles: state.serviceAccounts.builtInRoles,
  38. timezone: getTimeZone(state.user),
  39. };
  40. }
  41. const mapDispatchToProps = {
  42. loadServiceAccount,
  43. loadServiceAccountTokens,
  44. createServiceAccountToken,
  45. deleteServiceAccountToken,
  46. deleteServiceAccount,
  47. updateServiceAccount,
  48. fetchACOptions,
  49. };
  50. const connector = connect(mapStateToProps, mapDispatchToProps);
  51. type Props = OwnProps & ConnectedProps<typeof connector>;
  52. const ServiceAccountPageUnconnected = ({
  53. navModel,
  54. match,
  55. serviceAccount,
  56. tokens,
  57. timezone,
  58. isLoading,
  59. roleOptions,
  60. builtInRoles,
  61. loadServiceAccount,
  62. loadServiceAccountTokens,
  63. createServiceAccountToken,
  64. deleteServiceAccountToken,
  65. deleteServiceAccount,
  66. updateServiceAccount,
  67. fetchACOptions,
  68. }: Props) => {
  69. const [isModalOpen, setIsModalOpen] = useState(false);
  70. const [newToken, setNewToken] = useState('');
  71. useEffect(() => {
  72. const serviceAccountId = parseInt(match.params.id, 10);
  73. loadServiceAccount(serviceAccountId);
  74. loadServiceAccountTokens(serviceAccountId);
  75. if (contextSrv.licensedAccessControlEnabled()) {
  76. fetchACOptions();
  77. }
  78. }, [match, loadServiceAccount, loadServiceAccountTokens, fetchACOptions]);
  79. const onDeleteServiceAccountToken = (key: ApiKey) => {
  80. deleteServiceAccountToken(parseInt(match.params.id, 10), key.id!);
  81. };
  82. const onCreateToken = (token: ServiceAccountToken) => {
  83. createServiceAccountToken(serviceAccount.id, token, setNewToken);
  84. };
  85. const onModalClose = () => {
  86. setIsModalOpen(false);
  87. setNewToken('');
  88. };
  89. return (
  90. <Page navModel={navModel}>
  91. <Page.Contents isLoading={isLoading}>
  92. {serviceAccount && (
  93. <>
  94. <ServiceAccountProfile
  95. serviceAccount={serviceAccount}
  96. timeZone={timezone}
  97. roleOptions={roleOptions}
  98. builtInRoles={builtInRoles}
  99. updateServiceAccount={updateServiceAccount}
  100. deleteServiceAccount={deleteServiceAccount}
  101. />
  102. </>
  103. )}
  104. <div className="page-action-bar" style={{ justifyContent: 'space-between', alignItems: 'center' }}>
  105. <h3 className="page-heading" style={{ marginBottom: '0px' }}>
  106. Tokens
  107. </h3>
  108. <Button
  109. onClick={() => setIsModalOpen(true)}
  110. disabled={!contextSrv.hasPermission(AccessControlAction.ServiceAccountsWrite)}
  111. >
  112. Add token
  113. </Button>
  114. </div>
  115. {tokens && (
  116. <ServiceAccountTokensTable tokens={tokens} timeZone={timezone} onDelete={onDeleteServiceAccountToken} />
  117. )}
  118. {contextSrv.hasPermission(AccessControlAction.ServiceAccountsWrite) && (
  119. <CreateTokenModal
  120. isOpen={isModalOpen}
  121. token={newToken}
  122. onCreateToken={onCreateToken}
  123. onClose={onModalClose}
  124. />
  125. )}
  126. </Page.Contents>
  127. </Page>
  128. );
  129. };
  130. export const ServiceAccountPage = connector(ServiceAccountPageUnconnected);