Files
speckle-server/packages/frontend/src/components/dialogs/TokenDialog.vue
T
2021-02-17 17:14:58 +00:00

143 lines
3.8 KiB
Vue

<template>
<v-card class="pa-4" color="background2">
<v-card-title>
Create a New Personal Access Token
<v-spacer></v-spacer>
<v-btn text color="error" icon @click="clearAndClose">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<v-card-text>
<v-form v-show="!fullTokenResult">
<h3 class="mt-3">Token Scopes</h3>
<p>
It's good practice to limit the scopes of your token to the absolute minimum. For example,
if your application or script will only read and write streams, select just those scopes.
</p>
<v-select
v-model="selectedScopes"
label="Scopes"
multiple
required
:items="parsedScopes"
chips
:menu-props="{ maxWidth: 420 }"
></v-select>
<p v-if="selectedScopes.length === 0" class="error--text">Please select some scopes.</p>
<br />
<h3 class="mt-3">Token Name</h3>
<p>
A name to remember this token by - can be the name of the script or application you're
planning to use it in!
</p>
<v-text-field
v-model="name"
label="Token Name"
:rules="nameRules"
required
filled
autofocus
></v-text-field>
<br />
<v-btn @click="createToken">Save</v-btn>
<v-btn text color="error" @click="clearAndClose">Cancel</v-btn>
</v-form>
<div v-show="fullTokenResult">
<div class="text-center my-5">
<h2 class="mb-5 font-weight-normal">Your new token:</h2>
<code class="subtitle-1 pa-3 my-4">{{ fullTokenResult }}</code>
</div>
<v-alert type="info">
<b>Note:</b>
This is the first and last time you will be able to see the full token. Please copy paste
it somewhere safe now.
</v-alert>
<v-btn block color="primary" @click="clearAndClose">Close</v-btn>
</div>
</v-card-text>
</v-card>
</template>
<script>
import gql from 'graphql-tag'
export default {
props: {
show: {
type: Boolean,
default: false
}
},
apollo: {
scopes: {
query: gql`
query {
serverInfo {
scopes {
name
description
}
}
}
`,
update: (data) => data.serverInfo.scopes
}
},
data() {
return {
name: null,
nameRules: [
(v) => !!v || 'Name is required',
(v) => (v && v.length <= 60) || 'Name must be less than 60 characters'
],
selectedScopes: [],
fullTokenResult: null
}
},
computed: {
parsedScopes() {
if (!this.scopes) return []
let arr = []
for (let s of this.scopes) {
arr.push({ text: s.name, value: s.name })
arr.push({ header: s.description })
arr.push({ divider: true })
}
return arr
}
},
methods: {
clearAndClose() {
this.fullTokenResult = null
this.name = null
this.selectedScopes = []
this.$emit('close')
},
async createToken() {
this.$matomo && this.$matomo.trackPageView('user/token/create')
try {
let res = await this.$apollo.mutate({
mutation: gql`
mutation($token: ApiTokenCreateInput!) {
apiTokenCreate(token: $token)
}
`,
variables: {
token: {
name: this.name,
scopes: this.selectedScopes
}
}
})
this.fullTokenResult = res.data.apiTokenCreate
this.name = null
this.selectedScopes = []
this.$emit('token-added')
} catch (e) {
// TODO: how do we catch and display errors?
console.log(e)
}
}
}
}
</script>