After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 969 B |
After Width: | Height: | Size: 1005 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 25 KiB |
@ -0,0 +1,63 @@
|
||||
<template lang="pug">
|
||||
q-dialog(ref='dialogRef', @hide='onDialogHide', persistent)
|
||||
q-card(style='min-width: 600px;')
|
||||
q-card-section.card-header
|
||||
q-icon(name='img:/_assets/icons/fluent-key-2.svg', left, size='sm')
|
||||
span {{t(`admin.api.copyKeyTitle`)}}
|
||||
q-card-section.card-negative
|
||||
i18n-t(tag='span', keypath='admin.api.newKeyCopyWarn')
|
||||
template(#bold)
|
||||
strong {{t('admin.api.newKeyCopyWarnBold')}}
|
||||
q-form.q-py-sm
|
||||
q-item
|
||||
blueprint-icon.self-start(icon='binary-file')
|
||||
q-item-section
|
||||
q-input(
|
||||
type='textarea'
|
||||
outlined
|
||||
v-model='props.keyValue'
|
||||
dense
|
||||
hide-bottom-space
|
||||
:label='t(`admin.api.key`)'
|
||||
:aria-label='t(`admin.api.key`)'
|
||||
autofocus
|
||||
)
|
||||
q-card-actions.card-actions
|
||||
q-space
|
||||
q-btn(
|
||||
unelevated
|
||||
:label='t(`common.actions.close`)'
|
||||
color='primary'
|
||||
padding='xs md'
|
||||
@click='onDialogOK'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useDialogPluginComponent, useQuasar } from 'quasar'
|
||||
|
||||
// PROPS
|
||||
|
||||
const props = defineProps({
|
||||
keyValue: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
// EMITS
|
||||
|
||||
defineEmits([
|
||||
...useDialogPluginComponent.emits
|
||||
])
|
||||
|
||||
// QUASAR
|
||||
|
||||
const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent()
|
||||
const $q = useQuasar()
|
||||
|
||||
// I18N
|
||||
|
||||
const { t } = useI18n()
|
||||
</script>
|
@ -0,0 +1,253 @@
|
||||
<template lang="pug">
|
||||
q-dialog(ref='dialogRef', @hide='onDialogHide')
|
||||
q-card(style='min-width: 650px;')
|
||||
q-card-section.card-header
|
||||
q-icon(name='img:/_assets/icons/fluent-plus-plus.svg', left, size='sm')
|
||||
span {{t(`admin.api.newKeyTitle`)}}
|
||||
q-form.q-py-sm(ref='createKeyForm', @submit='create')
|
||||
q-item
|
||||
blueprint-icon.self-start(icon='grand-master-key')
|
||||
q-item-section
|
||||
q-input(
|
||||
outlined
|
||||
v-model='state.keyName'
|
||||
dense
|
||||
:rules='keyNameValidation'
|
||||
hide-bottom-space
|
||||
:label='t(`admin.api.newKeyName`)'
|
||||
:aria-label='t(`admin.api.newKeyName`)'
|
||||
:hint='t(`admin.api.newKeyNameHint`)'
|
||||
lazy-rules='ondemand'
|
||||
autofocus
|
||||
ref='iptName'
|
||||
)
|
||||
q-item
|
||||
blueprint-icon.self-start(icon='schedule')
|
||||
q-item-section
|
||||
q-select(
|
||||
outlined
|
||||
:options='expirations'
|
||||
v-model='state.keyExpiration'
|
||||
multiple
|
||||
map-options
|
||||
option-value='value'
|
||||
option-label='text'
|
||||
emit-value
|
||||
options-dense
|
||||
dense
|
||||
hide-bottom-space
|
||||
:label='t(`admin.api.newKeyExpiration`)'
|
||||
:aria-label='t(`admin.api.newKeyExpiration`)'
|
||||
:hint='t(`admin.api.newKeyExpirationHint`)'
|
||||
)
|
||||
q-item
|
||||
blueprint-icon.self-start(icon='access')
|
||||
q-item-section
|
||||
q-select(
|
||||
outlined
|
||||
:options='state.groups'
|
||||
v-model='state.keyGroups'
|
||||
multiple
|
||||
map-options
|
||||
emit-value
|
||||
option-value='id'
|
||||
option-label='name'
|
||||
options-dense
|
||||
dense
|
||||
:rules='keyGroupsValidation'
|
||||
hide-bottom-space
|
||||
:label='t(`admin.api.permissionGroups`)'
|
||||
:aria-label='t(`admin.api.permissionGroups`)'
|
||||
:hint='t(`admin.api.newKeyGroupHint`)'
|
||||
lazy-rules='ondemand'
|
||||
:loading='state.loadingGroups'
|
||||
)
|
||||
template(v-slot:selected)
|
||||
.text-caption(v-if='state.keyGroups.length > 1')
|
||||
i18n-t(keypath='admin.api.groupsSelected')
|
||||
template(#count)
|
||||
strong {{ state.keyGroups.length }}
|
||||
.text-caption(v-else-if='state.keyGroups.length === 1')
|
||||
i18n-t(keypath='admin.api.groupSelected')
|
||||
template(#group)
|
||||
strong {{ selectedGroupName }}
|
||||
span(v-else)
|
||||
template(v-slot:option='{ itemProps, opt, selected, toggleOption }')
|
||||
q-item(
|
||||
v-bind='itemProps'
|
||||
)
|
||||
q-item-section(side)
|
||||
q-checkbox(
|
||||
size='sm'
|
||||
:model-value='selected'
|
||||
@update:model-value='toggleOption(opt)'
|
||||
)
|
||||
q-item-section
|
||||
q-item-label {{opt.name}}
|
||||
q-card-actions.card-actions
|
||||
q-space
|
||||
q-btn.acrylic-btn(
|
||||
flat
|
||||
:label='t(`common.actions.cancel`)'
|
||||
color='grey'
|
||||
padding='xs md'
|
||||
@click='onDialogCancel'
|
||||
)
|
||||
q-btn(
|
||||
unelevated
|
||||
:label='t(`common.actions.create`)'
|
||||
color='primary'
|
||||
padding='xs md'
|
||||
@click='create'
|
||||
:loading='state.loading > 0'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import gql from 'graphql-tag'
|
||||
import { cloneDeep, sampleSize } from 'lodash-es'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useDialogPluginComponent, useQuasar } from 'quasar'
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
|
||||
import ApiKeyCopyDialog from './ApiKeyCopyDialog.vue'
|
||||
|
||||
// EMITS
|
||||
|
||||
defineEmits([
|
||||
...useDialogPluginComponent.emits
|
||||
])
|
||||
|
||||
// QUASAR
|
||||
|
||||
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
|
||||
const $q = useQuasar()
|
||||
|
||||
// I18N
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// DATA
|
||||
|
||||
const state = reactive({
|
||||
keyName: '',
|
||||
keyExpiration: '90d',
|
||||
keyGroups: [],
|
||||
groups: [],
|
||||
loadingGroups: false,
|
||||
loading: false
|
||||
})
|
||||
|
||||
const expirations = [
|
||||
{ value: '30d', text: t('admin.api.expiration30d') },
|
||||
{ value: '90d', text: t('admin.api.expiration90d') },
|
||||
{ value: '180d', text: t('admin.api.expiration180d') },
|
||||
{ value: '1y', text: t('admin.api.expiration1y') },
|
||||
{ value: '3y', text: t('admin.api.expiration3y') }
|
||||
]
|
||||
|
||||
// REFS
|
||||
|
||||
const createKeyForm = ref(null)
|
||||
const iptName = ref(null)
|
||||
|
||||
// COMPUTED
|
||||
|
||||
const selectedGroupName = computed(() => {
|
||||
return state.groups.filter(g => g.id === state.keyGroups[0])[0]?.name
|
||||
})
|
||||
|
||||
// VALIDATION RULES
|
||||
|
||||
const keyNameValidation = [
|
||||
val => val.length > 0 || t('admin.api.nameMissing'),
|
||||
val => /^[^<>"]+$/.test(val) || t('admin.api.nameInvalidChars')
|
||||
]
|
||||
|
||||
const keyGroupsValidation = [
|
||||
val => val.length > 0 || t('admin.api.groupsMissing')
|
||||
]
|
||||
|
||||
// METHODS
|
||||
|
||||
async function loadGroups () {
|
||||
state.loading++
|
||||
state.loadingGroups = true
|
||||
const resp = await APOLLO_CLIENT.query({
|
||||
query: gql`
|
||||
query getGroupsForCreateApiKey {
|
||||
groups {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`,
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
state.groups = cloneDeep(resp?.data?.groups?.filter(g => g.id !== '10000000-0000-4000-8000-000000000001') ?? [])
|
||||
state.loadingGroups = false
|
||||
state.loading--
|
||||
}
|
||||
|
||||
async function create () {
|
||||
state.loading++
|
||||
try {
|
||||
const isFormValid = await createKeyForm.value.validate(true)
|
||||
if (!isFormValid) {
|
||||
throw new Error(t('admin.api.createInvalidData'))
|
||||
}
|
||||
const resp = await APOLLO_CLIENT.mutate({
|
||||
mutation: gql`
|
||||
mutation createApiKey (
|
||||
$name: String!
|
||||
$expiration: String!
|
||||
$groups: [UUID]!
|
||||
) {
|
||||
createApiKey (
|
||||
name: $name
|
||||
expiration: $expiration
|
||||
groups: $groups
|
||||
) {
|
||||
operation {
|
||||
succeeded
|
||||
message
|
||||
}
|
||||
key
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
name: state.keyName,
|
||||
expiration: state.keyExpiration,
|
||||
groups: state.keyGroups
|
||||
}
|
||||
})
|
||||
if (resp?.data?.createApiKey?.operation?.succeeded) {
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: t('admin.api.createSuccess')
|
||||
})
|
||||
$q.dialog({
|
||||
component: ApiKeyCopyDialog,
|
||||
componentProps: {
|
||||
keyValue: resp?.data?.createApiKey?.key || 'ERROR'
|
||||
}
|
||||
}).onDismiss(() => {
|
||||
onDialogOK()
|
||||
})
|
||||
} else {
|
||||
throw new Error(resp?.data?.createApiKey?.operation?.message || 'An unexpected error occured.')
|
||||
}
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: err.message
|
||||
})
|
||||
}
|
||||
state.loading--
|
||||
}
|
||||
|
||||
// MOUNTED
|
||||
|
||||
onMounted(loadGroups)
|
||||
</script>
|
@ -0,0 +1,104 @@
|
||||
<template lang="pug">
|
||||
q-dialog(ref='dialogRef', @hide='onDialogHide')
|
||||
q-card(style='min-width: 350px; max-width: 450px;')
|
||||
q-card-section.card-header
|
||||
q-icon(name='img:/_assets/icons/fluent-unavailable.svg', left, size='sm')
|
||||
span {{t(`admin.api.revokeConfirm`)}}
|
||||
q-card-section
|
||||
.text-body2
|
||||
i18n-t(keypath='admin.api.revokeConfirmText')
|
||||
template(#name)
|
||||
strong {{apiKey.name}}
|
||||
q-card-actions.card-actions
|
||||
q-space
|
||||
q-btn.acrylic-btn(
|
||||
flat
|
||||
:label='t(`common.actions.cancel`)'
|
||||
color='grey'
|
||||
padding='xs md'
|
||||
@click='onDialogCancel'
|
||||
)
|
||||
q-btn(
|
||||
unelevated
|
||||
:label='t(`admin.api.revoke`)'
|
||||
color='negative'
|
||||
padding='xs md'
|
||||
@click='confirm'
|
||||
:loading='state.isLoading'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import gql from 'graphql-tag'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useDialogPluginComponent, useQuasar } from 'quasar'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
// PROPS
|
||||
|
||||
const props = defineProps({
|
||||
apiKey: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
// EMITS
|
||||
|
||||
defineEmits([
|
||||
...useDialogPluginComponent.emits
|
||||
])
|
||||
|
||||
// QUASAR
|
||||
|
||||
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
|
||||
const $q = useQuasar()
|
||||
|
||||
// I18N
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// DATA
|
||||
|
||||
const state = reactive({
|
||||
isLoading: false
|
||||
})
|
||||
|
||||
// METHODS
|
||||
|
||||
async function confirm () {
|
||||
state.isLoading = true
|
||||
try {
|
||||
const resp = await APOLLO_CLIENT.mutate({
|
||||
mutation: gql`
|
||||
mutation revokeApiKey ($id: UUID!) {
|
||||
revokeApiKey (id: $id) {
|
||||
operation {
|
||||
succeeded
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
id: props.apiKey.id
|
||||
}
|
||||
})
|
||||
if (resp?.data?.revokeApiKey?.operation?.succeeded) {
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: t('admin.api.revokeSuccess')
|
||||
})
|
||||
onDialogOK()
|
||||
} else {
|
||||
throw new Error(resp?.data?.revokeApiKey?.operation?.message || 'An unexpected error occured.')
|
||||
}
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: err.message
|
||||
})
|
||||
}
|
||||
state.isLoading = false
|
||||
}
|
||||
</script>
|
@ -0,0 +1,101 @@
|
||||
<template lang="pug">
|
||||
q-dialog(ref='dialogRef', @hide='onDialogHide')
|
||||
q-card(style='min-width: 350px; max-width: 450px;')
|
||||
q-card-section.card-header
|
||||
q-icon(name='img:/_assets/icons/fluent-downloading-updates.svg', left, size='sm')
|
||||
span {{t(`admin.system.checkingForUpdates`)}}
|
||||
q-card-section
|
||||
.q-pa-md.text-center
|
||||
img(src='/_assets/illustrations/undraw_going_up.svg', style='width: 150px;')
|
||||
q-linear-progress(
|
||||
indeterminate
|
||||
size='lg'
|
||||
rounded
|
||||
)
|
||||
.q-mt-sm.text-center.text-caption Fetching latest version info...
|
||||
q-card-actions.card-actions
|
||||
q-space
|
||||
q-btn.acrylic-btn(
|
||||
flat
|
||||
:label='t(`common.actions.cancel`)'
|
||||
color='grey'
|
||||
padding='xs md'
|
||||
@click='onDialogCancel'
|
||||
)
|
||||
q-btn(
|
||||
v-if='state.canUpgrade'
|
||||
unelevated
|
||||
:label='t(`admin.system.upgrade`)'
|
||||
color='primary'
|
||||
padding='xs md'
|
||||
@click='upgrade'
|
||||
:loading='state.isLoading'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import gql from 'graphql-tag'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useDialogPluginComponent, useQuasar } from 'quasar'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
// EMITS
|
||||
|
||||
defineEmits([
|
||||
...useDialogPluginComponent.emits
|
||||
])
|
||||
|
||||
// QUASAR
|
||||
|
||||
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
|
||||
const $q = useQuasar()
|
||||
|
||||
// I18N
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// DATA
|
||||
|
||||
const state = reactive({
|
||||
isLoading: false,
|
||||
canUpgrade: false
|
||||
})
|
||||
|
||||
// METHODS
|
||||
|
||||
async function upgrade () {
|
||||
state.isLoading = true
|
||||
try {
|
||||
const resp = await APOLLO_CLIENT.mutate({
|
||||
mutation: gql`
|
||||
mutation deleteHook ($id: UUID!) {
|
||||
deleteHook(id: $id) {
|
||||
operation {
|
||||
succeeded
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
id: 0
|
||||
}
|
||||
})
|
||||
if (resp?.data?.deleteHook?.operation?.succeeded) {
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: t('admin.webhooks.deleteSuccess')
|
||||
})
|
||||
onDialogOK()
|
||||
} else {
|
||||
throw new Error(resp?.data?.deleteHook?.operation?.message || 'An unexpected error occured.')
|
||||
}
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: err.message
|
||||
})
|
||||
}
|
||||
state.isLoading = false
|
||||
}
|
||||
</script>
|
@ -1,236 +0,0 @@
|
||||
<template lang="pug">
|
||||
div
|
||||
v-dialog(v-model='isShown', max-width='650', persistent)
|
||||
v-card
|
||||
.dialog-header.is-short
|
||||
v-icon.mr-3(color='white') mdi-plus
|
||||
span {{$t('admin.api.newKeyTitle')}}
|
||||
v-card-text.pt-5
|
||||
v-text-field(
|
||||
outlined
|
||||
prepend-icon='mdi-format-title'
|
||||
v-model='name'
|
||||
:label='$t(`admin.api.newKeyName`)'
|
||||
persistent-hint
|
||||
ref='keyNameInput'
|
||||
:hint='$t(`admin.api.newKeyNameHint`)'
|
||||
counter='255'
|
||||
)
|
||||
v-select.mt-3(
|
||||
:items='expirations'
|
||||
outlined
|
||||
prepend-icon='mdi-clock'
|
||||
v-model='expiration'
|
||||
:label='$t(`admin.api.newKeyExpiration`)'
|
||||
:hint='$t(`admin.api.newKeyExpirationHint`)'
|
||||
persistent-hint
|
||||
)
|
||||
v-divider.mt-4
|
||||
v-subheader.pl-2: strong.indigo--text {{$t('admin.api.newKeyPermissionScopes')}}
|
||||
v-list.pl-8(nav)
|
||||
v-list-item-group(v-model='fullAccess')
|
||||
v-list-item(
|
||||
:value='true'
|
||||
active-class='indigo--text'
|
||||
)
|
||||
template(v-slot:default='{ active, toggle }')
|
||||
v-list-item-action
|
||||
v-checkbox(
|
||||
:input-value='active'
|
||||
:true-value='true'
|
||||
color='indigo'
|
||||
@click='toggle'
|
||||
)
|
||||
v-list-item-content
|
||||
v-list-item-title {{$t('admin.api.newKeyFullAccess')}}
|
||||
v-divider.mt-3
|
||||
v-subheader.caption.indigo--text {{$t('admin.api.newKeyGroupPermissions')}}
|
||||
v-list-item
|
||||
v-select(
|
||||
:disabled='fullAccess'
|
||||
:items='groups'
|
||||
item-text='name'
|
||||
item-value='id'
|
||||
outlined
|
||||
color='indigo'
|
||||
v-model='group'
|
||||
:label='$t(`admin.api.newKeyGroup`)'
|
||||
:hint='$t(`admin.api.newKeyGroupHint`)'
|
||||
persistent-hint
|
||||
)
|
||||
v-card-chin
|
||||
v-spacer
|
||||
v-btn(text, @click='isShown = false', :disabled='loading') {{$t('common.actions.cancel')}}
|
||||
v-btn.px-3(depressed, color='primary', @click='generate', :loading='loading')
|
||||
v-icon(left) mdi-chevron-right
|
||||
span {{$t('common.actions.generate')}}
|
||||
|
||||
v-dialog(
|
||||
v-model='isCopyKeyDialogShown'
|
||||
max-width='750'
|
||||
persistent
|
||||
overlay-color='blue darken-5'
|
||||
overlay-opacity='.9'
|
||||
)
|
||||
v-card
|
||||
v-toolbar(dense, flat, color='primary', dark) {{$t('admin.api.newKeyTitle')}}
|
||||
v-card-text.pt-5
|
||||
.body-2.text-center
|
||||
i18next(tag='span', path='admin.api.newKeyCopyWarn')
|
||||
strong(place='bold') {{$t('admin.api.newKeyCopyWarnBold')}}
|
||||
v-textarea.mt-3(
|
||||
ref='keyContentsIpt'
|
||||
filled
|
||||
no-resize
|
||||
readonly
|
||||
v-model='key'
|
||||
:rows='10'
|
||||
hide-details
|
||||
)
|
||||
v-card-chin
|
||||
v-spacer
|
||||
v-btn.px-3(depressed, dark, color='primary', @click='isCopyKeyDialogShown = false') {{$t('common.actions.close')}}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import _ from 'lodash'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
import groupsQuery from 'gql/admin/users/users-query-groups.gql'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
name: '',
|
||||
expiration: '1y',
|
||||
fullAccess: true,
|
||||
groups: [],
|
||||
group: null,
|
||||
isCopyKeyDialogShown: false,
|
||||
key: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isShown: {
|
||||
get() { return this.value },
|
||||
set(val) { this.$emit('input', val) }
|
||||
},
|
||||
expirations() {
|
||||
return [
|
||||
{ value: '30d', text: this.$t('admin.api.expiration30d') },
|
||||
{ value: '90d', text: this.$t('admin.api.expiration90d') },
|
||||
{ value: '180d', text: this.$t('admin.api.expiration180d') },
|
||||
{ value: '1y', text: this.$t('admin.api.expiration1y') },
|
||||
{ value: '3y', text: this.$t('admin.api.expiration3y') }
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (newValue, oldValue) {
|
||||
if (newValue) {
|
||||
setTimeout(() => {
|
||||
this.$refs.keyNameInput.focus()
|
||||
}, 400)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async generate () {
|
||||
try {
|
||||
if (_.trim(this.name).length < 2 || this.name.length > 255) {
|
||||
throw new Error(this.$t('admin.api.newKeyNameError'))
|
||||
} else if (!this.fullAccess && !this.group) {
|
||||
throw new Error(this.$t('admin.api.newKeyGroupError'))
|
||||
} else if (!this.fullAccess && this.group === 2) {
|
||||
throw new Error(this.$t('admin.api.newKeyGuestGroupError'))
|
||||
}
|
||||
} catch (err) {
|
||||
return this.$store.commit('showNotification', {
|
||||
style: 'red',
|
||||
message: err,
|
||||
icon: 'alert'
|
||||
})
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
|
||||
try {
|
||||
const resp = await this.$apollo.mutate({
|
||||
mutation: gql`
|
||||
mutation ($name: String!, $expiration: String!, $fullAccess: Boolean!, $group: Int) {
|
||||
authentication {
|
||||
createApiKey (name: $name, expiration: $expiration, fullAccess: $fullAccess, group: $group) {
|
||||
key
|
||||
responseResult {
|
||||
succeeded
|
||||
errorCode
|
||||
slug
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
name: this.name,
|
||||
expiration: this.expiration,
|
||||
fullAccess: (this.fullAccess === true),
|
||||
group: this.group
|
||||
},
|
||||
watchLoading (isLoading) {
|
||||
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-api-create')
|
||||
}
|
||||
})
|
||||
if (_.get(resp, 'data.authentication.createApiKey.responseResult.succeeded', false)) {
|
||||
this.$store.commit('showNotification', {
|
||||
style: 'success',
|
||||
message: this.$t('admin.api.newKeySuccess'),
|
||||
icon: 'check'
|
||||
})
|
||||
|
||||
this.name = ''
|
||||
this.expiration = '1y'
|
||||
this.fullAccess = true
|
||||
this.group = null
|
||||
this.isShown = false
|
||||
this.$emit('refresh')
|
||||
|
||||
this.key = _.get(resp, 'data.authentication.createApiKey.key', '???')
|
||||
this.isCopyKeyDialogShown = true
|
||||
|
||||
setTimeout(() => {
|
||||
this.$refs.keyContentsIpt.$refs.input.select()
|
||||
}, 400)
|
||||
} else {
|
||||
this.$store.commit('showNotification', {
|
||||
style: 'red',
|
||||
message: _.get(resp, 'data.authentication.createApiKey.responseResult.message', 'An unexpected error occurred.'),
|
||||
icon: 'alert'
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
this.$store.commit('pushGraphError', err)
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
groups: {
|
||||
query: groupsQuery,
|
||||
fetchPolicy: 'network-only',
|
||||
update: (data) => data.groups.list,
|
||||
watchLoading (isLoading) {
|
||||
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-api-groups-refresh')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|