/pkg/webui/console/components/api-key-form/edit.js

https://github.com/TheThingsNetwork/lorawan-stack · JavaScript · 218 lines · 150 code · 25 blank · 43 comment · 0 complexity · 359704235440ebf82acbc1b49cd98139 MD5 · raw file

  1. // Copyright © 2019 The Things Network Foundation, The Things Industries B.V.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import React from 'react'
  15. import bind from 'autobind-decorator'
  16. import { defineMessages } from 'react-intl'
  17. import SubmitBar from '@ttn-lw/components/submit-bar'
  18. import ModalButton from '@ttn-lw/components/button/modal-button'
  19. import toast from '@ttn-lw/components/toast'
  20. import FormField from '@ttn-lw/components/form/field'
  21. import FormSubmit from '@ttn-lw/components/form/submit'
  22. import SubmitButton from '@ttn-lw/components/submit-button'
  23. import Input from '@ttn-lw/components/input'
  24. import Message from '@ttn-lw/lib/components/message'
  25. import RightsGroup from '@console/components/rights-group'
  26. import sharedMessages from '@ttn-lw/lib/shared-messages'
  27. import PropTypes from '@ttn-lw/lib/prop-types'
  28. import ApiKeyForm from './form'
  29. import validationSchema from './validation-schema'
  30. const m = defineMessages({
  31. deleteKey: 'Delete key',
  32. modalWarning:
  33. 'Are you sure you want to delete the {keyName} API key? Deleting an API key cannot be undone.',
  34. updateSuccess: 'API key updated',
  35. deleteSuccess: 'API key deleted',
  36. })
  37. class EditForm extends React.Component {
  38. static propTypes = {
  39. /** The API key to be edited. */
  40. apiKey: PropTypes.apiKey,
  41. /**
  42. * Called on key deletion. Receives the identifier of the API key as an
  43. * argument.
  44. */
  45. onDelete: PropTypes.func.isRequired,
  46. /**
  47. * Called after unsuccessful deletion of the API key. Receives the error
  48. * object as an argument.
  49. */
  50. onDeleteFailure: PropTypes.func,
  51. /**
  52. * Called after successful deletion of the API key. Receives the identifier
  53. * of the API key as an argument.
  54. */
  55. onDeleteSuccess: PropTypes.func.isRequired,
  56. /**
  57. * Called on form submission. Receives the updated key object as an
  58. * argument.
  59. */
  60. onEdit: PropTypes.func.isRequired,
  61. /**
  62. * Called after unsuccessful update of the API key. Receives the error
  63. * object as an argument.
  64. */
  65. onEditFailure: PropTypes.func,
  66. /**
  67. * Called after successful update of the API key. Receives the key object as
  68. * an argument.
  69. */
  70. onEditSuccess: PropTypes.func,
  71. /**
  72. * The rights that imply all other rights, e.g. 'RIGHT_APPLICATION_ALL',
  73. * 'RIGHT_ALL'.
  74. */
  75. pseudoRights: PropTypes.arrayOf(PropTypes.string),
  76. /** The list of rights. */
  77. rights: PropTypes.arrayOf(PropTypes.string),
  78. }
  79. state = {
  80. error: null,
  81. }
  82. static defaultProps = {
  83. apiKey: undefined,
  84. rights: [],
  85. onEditFailure: () => null,
  86. onEditSuccess: () => null,
  87. onDeleteFailure: () => null,
  88. pseudoRights: [],
  89. }
  90. @bind
  91. async handleEdit(values) {
  92. const { name, rights } = values
  93. const { onEdit } = this.props
  94. return await onEdit({ name, rights })
  95. }
  96. @bind
  97. async handleEditSuccess(key) {
  98. const { onEditSuccess } = this.props
  99. toast({
  100. message: m.updateSuccess,
  101. type: toast.types.SUCCESS,
  102. })
  103. await onEditSuccess(key)
  104. }
  105. @bind
  106. async handleDelete() {
  107. const { onDelete, apiKey } = this.props
  108. await this.setState({ error: null })
  109. try {
  110. await onDelete(apiKey.id)
  111. await this.handleDeleteSuccess(apiKey.id)
  112. } catch (error) {
  113. await this.handleDeleteFailure(error)
  114. }
  115. }
  116. @bind
  117. async handleDeleteSuccess(id) {
  118. const { onDeleteSuccess } = this.props
  119. toast({
  120. message: m.deleteSuccess,
  121. type: toast.types.SUCCESS,
  122. })
  123. await onDeleteSuccess(id)
  124. }
  125. @bind
  126. async handleDeleteFailure(error) {
  127. const { onDeleteFailure } = this.props
  128. await this.setState({ error })
  129. await onDeleteFailure(error)
  130. }
  131. render() {
  132. const { rights, apiKey, onEditFailure, pseudoRights } = this.props
  133. const { error } = this.state
  134. const initialValues = {
  135. id: apiKey.id,
  136. name: apiKey.name,
  137. rights: apiKey.rights,
  138. }
  139. return (
  140. <ApiKeyForm
  141. formError={error}
  142. initialValues={initialValues}
  143. validationSchema={validationSchema}
  144. onSubmit={this.handleEdit}
  145. onSubmitSuccess={this.handleEditSuccess}
  146. onSubmitFailure={onEditFailure}
  147. >
  148. <Message component="h4" content={sharedMessages.generalInformation} />
  149. <FormField
  150. title={sharedMessages.keyId}
  151. name="id"
  152. required
  153. valid
  154. disabled
  155. component={Input}
  156. />
  157. <FormField
  158. title={sharedMessages.name}
  159. placeholder={sharedMessages.apiKeyNamePlaceholder}
  160. name="name"
  161. component={Input}
  162. />
  163. <FormField
  164. name="rights"
  165. title={sharedMessages.rights}
  166. required
  167. component={RightsGroup}
  168. rights={rights}
  169. pseudoRight={pseudoRights[0]}
  170. entityTypeMessage={sharedMessages.apiKey}
  171. />
  172. <SubmitBar>
  173. <FormSubmit component={SubmitButton} message={sharedMessages.saveChanges} />
  174. <ModalButton
  175. type="button"
  176. icon="delete"
  177. danger
  178. naked
  179. message={m.deleteKey}
  180. modalData={{
  181. message: {
  182. values: { keyName: apiKey.name ? `"${apiKey.name}"` : '' },
  183. ...m.modalWarning,
  184. },
  185. }}
  186. onApprove={this.handleDelete}
  187. />
  188. </SubmitBar>
  189. </ApiKeyForm>
  190. )
  191. }
  192. }
  193. export default EditForm