You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
7.2 KiB

  1. <template lang="pug">
  2. div
  3. v-dialog(v-model='isShown', max-width='650', persistent)
  4. v-card
  5. .dialog-header.is-short
  6. v-icon.mr-3(color='white') mdi-plus
  7. span {{$t('admin:api.newKeyTitle')}}
  8. v-card-text.pt-5
  9. v-text-field(
  10. outlined
  11. prepend-icon='mdi-format-title'
  12. v-model='name'
  13. :label='$t(`admin:api.newKeyName`)'
  14. persistent-hint
  15. ref='keyNameInput'
  16. :hint='$t(`admin:api.newKeyNameHint`)'
  17. counter='255'
  18. )
  19. v-select.mt-3(
  20. :items='expirations'
  21. outlined
  22. prepend-icon='mdi-clock'
  23. v-model='expiration'
  24. :label='$t(`admin:api.newKeyExpiration`)'
  25. :hint='$t(`admin:api.newKeyExpirationHint`)'
  26. persistent-hint
  27. )
  28. v-divider.mt-4
  29. v-subheader.pl-2: strong.indigo--text {{$t('admin:api.newKeyPermissionScopes')}}
  30. v-list.pl-8(nav)
  31. v-list-item-group(v-model='fullAccess')
  32. v-list-item(
  33. :value='true'
  34. active-class='indigo--text'
  35. )
  36. template(v-slot:default='{ active, toggle }')
  37. v-list-item-action
  38. v-checkbox(
  39. :input-value='active'
  40. :true-value='true'
  41. color='indigo'
  42. @click='toggle'
  43. )
  44. v-list-item-content
  45. v-list-item-title {{$t('admin:api.newKeyFullAccess')}}
  46. v-divider.mt-3
  47. v-subheader.caption.indigo--text {{$t('admin:api.newKeyGroupPermissions')}}
  48. v-list-item
  49. v-select(
  50. :disabled='fullAccess'
  51. :items='groups'
  52. item-text='name'
  53. item-value='id'
  54. outlined
  55. color='indigo'
  56. v-model='group'
  57. :label='$t(`admin:api.newKeyGroup`)'
  58. :hint='$t(`admin:api.newKeyGroupHint`)'
  59. persistent-hint
  60. )
  61. v-card-chin
  62. v-spacer
  63. v-btn(text, @click='isShown = false', :disabled='loading') {{$t('common:actions.cancel')}}
  64. v-btn.px-3(depressed, color='primary', @click='generate', :loading='loading')
  65. v-icon(left) mdi-chevron-right
  66. span {{$t('common:actions.generate')}}
  67. v-dialog(
  68. v-model='isCopyKeyDialogShown'
  69. max-width='750'
  70. persistent
  71. overlay-color='blue darken-5'
  72. overlay-opacity='.9'
  73. )
  74. v-card
  75. v-toolbar(dense, flat, color='primary', dark) {{$t('admin:api.newKeyTitle')}}
  76. v-card-text.pt-5
  77. .body-2.text-center
  78. i18next(tag='span', path='admin:api.newKeyCopyWarn')
  79. strong(place='bold') {{$t('admin:api.newKeyCopyWarnBold')}}
  80. v-textarea.mt-3(
  81. ref='keyContentsIpt'
  82. filled
  83. no-resize
  84. readonly
  85. v-model='key'
  86. :rows='10'
  87. hide-details
  88. )
  89. v-card-chin
  90. v-spacer
  91. v-btn.px-3(depressed, dark, color='primary', @click='isCopyKeyDialogShown = false') {{$t('common:actions.close')}}
  92. </template>
  93. <script>
  94. import _ from 'lodash'
  95. import gql from 'graphql-tag'
  96. import groupsQuery from 'gql/admin/users/users-query-groups.gql'
  97. export default {
  98. props: {
  99. value: {
  100. type: Boolean,
  101. default: false
  102. }
  103. },
  104. data() {
  105. return {
  106. loading: false,
  107. name: '',
  108. expiration: '1y',
  109. fullAccess: true,
  110. groups: [],
  111. group: null,
  112. isCopyKeyDialogShown: false,
  113. key: ''
  114. }
  115. },
  116. computed: {
  117. isShown: {
  118. get() { return this.value },
  119. set(val) { this.$emit('input', val) }
  120. },
  121. expirations() {
  122. return [
  123. { value: '30d', text: this.$t('admin:api.expiration30d') },
  124. { value: '90d', text: this.$t('admin:api.expiration90d') },
  125. { value: '180d', text: this.$t('admin:api.expiration180d') },
  126. { value: '1y', text: this.$t('admin:api.expiration1y') },
  127. { value: '3y', text: this.$t('admin:api.expiration3y') }
  128. ]
  129. }
  130. },
  131. watch: {
  132. value (newValue, oldValue) {
  133. if (newValue) {
  134. setTimeout(() => {
  135. this.$refs.keyNameInput.focus()
  136. }, 400)
  137. }
  138. }
  139. },
  140. methods: {
  141. async generate () {
  142. try {
  143. if (_.trim(this.name).length < 2 || this.name.length > 255) {
  144. throw new Error(this.$t('admin:api.newKeyNameError'))
  145. } else if (!this.fullAccess && !this.group) {
  146. throw new Error(this.$t('admin:api.newKeyGroupError'))
  147. } else if (!this.fullAccess && this.group === 2) {
  148. throw new Error(this.$t('admin:api.newKeyGuestGroupError'))
  149. }
  150. } catch (err) {
  151. return this.$store.commit('showNotification', {
  152. style: 'red',
  153. message: err,
  154. icon: 'alert'
  155. })
  156. }
  157. this.loading = true
  158. try {
  159. const resp = await this.$apollo.mutate({
  160. mutation: gql`
  161. mutation ($name: String!, $expiration: String!, $fullAccess: Boolean!, $group: Int) {
  162. authentication {
  163. createApiKey (name: $name, expiration: $expiration, fullAccess: $fullAccess, group: $group) {
  164. key
  165. responseResult {
  166. succeeded
  167. errorCode
  168. slug
  169. message
  170. }
  171. }
  172. }
  173. }
  174. `,
  175. variables: {
  176. name: this.name,
  177. expiration: this.expiration,
  178. fullAccess: (this.fullAccess === true),
  179. group: this.group
  180. },
  181. watchLoading (isLoading) {
  182. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-api-create')
  183. }
  184. })
  185. if (_.get(resp, 'data.authentication.createApiKey.responseResult.succeeded', false)) {
  186. this.$store.commit('showNotification', {
  187. style: 'success',
  188. message: this.$t('admin:api.newKeySuccess'),
  189. icon: 'check'
  190. })
  191. this.name = ''
  192. this.expiration = '1y'
  193. this.fullAccess = true
  194. this.group = null
  195. this.isShown = false
  196. this.$emit('refresh')
  197. this.key = _.get(resp, 'data.authentication.createApiKey.key', '???')
  198. this.isCopyKeyDialogShown = true
  199. setTimeout(() => {
  200. this.$refs.keyContentsIpt.$refs.input.select()
  201. }, 400)
  202. } else {
  203. this.$store.commit('showNotification', {
  204. style: 'red',
  205. message: _.get(resp, 'data.authentication.createApiKey.responseResult.message', 'An unexpected error occurred.'),
  206. icon: 'alert'
  207. })
  208. }
  209. } catch (err) {
  210. this.$store.commit('pushGraphError', err)
  211. }
  212. this.loading = false
  213. }
  214. },
  215. apollo: {
  216. groups: {
  217. query: groupsQuery,
  218. fetchPolicy: 'network-only',
  219. update: (data) => data.groups.list,
  220. watchLoading (isLoading) {
  221. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-api-groups-refresh')
  222. }
  223. }
  224. }
  225. }
  226. </script>