feat(frontend): token revokation and creation

This commit is contained in:
Dimitrie Stefanescu
2020-12-11 00:03:02 +00:00
parent 3510aa443b
commit 6cfec100f4
3 changed files with 104 additions and 30 deletions
@@ -2,27 +2,38 @@
<v-list-item>
<v-list-item-content>
<v-list-item-title>
<v-chip small outlined class="mr-2">{{ token.lastChars }}</v-chip>
<v-chip small class="mr-2">{{ token.id }}</v-chip>
<b>{{ token.name }}</b>
</v-list-item-title>
<v-list-item-subtitle>
Created:
{{ token.createdAt | dateParse() | dateFormat("DD MMM YY") }} (
<timeago :datetime="token.createdAt"></timeago>
) Last Used:
{{ token.lastUsed | dateParse() | dateFormat("DD MMM YY") }} (
<timeago :datetime="token.lastUsed"></timeago>
)
<v-list-item-subtitle class="caption">
<b>Created:</b>
{{ token.createdAt | dateParse() | dateFormat("DD MMM YYYY") }}
<b>Last Used:</b>
{{ token.lastUsed | dateParse() | dateFormat("DD MMM YYYY") }}
</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-action>
<v-btn small icon>
<v-btn small icon @click="showRevokeConfirm = true">
<v-icon color="error">mdi-delete</v-icon>
</v-btn>
</v-list-item-action>
<v-dialog v-model="showRevokeConfirm" width="500">
<v-card class="pa-3">
<v-card-title>Are you sure?</v-card-title>
<v-card-text>
You cannot undo this action. This will permanently delete this token.
</v-card-text>
<v-card-actions>
<v-btn color="error" @click="revokeToken">Delete</v-btn>
<v-btn @click="showRevokeConfirm = false">Cancel</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-list-item>
</template>
<script>
import gql from "graphql-tag"
export default {
components: {},
props: {
@@ -31,9 +42,26 @@ export default {
default: () => {}
}
},
data() {
return {
showRevokeConfirm: false
}
},
methods: {
revokeToken() {
// TODO
async revokeToken() {
try {
await this.$apollo.mutate({
mutation: gql`
mutation {
apiTokenRevoke(token: "${this.token.id}")
}
`
})
this.$emit('deleted')
this.showRevokeConfirm = false
} catch (e) {
console.log(e)
}
}
}
}
+14 -5
View File
@@ -3,8 +3,12 @@
<v-card-title>Personal Access Tokens</v-card-title>
<v-card-text>
Personal Access Tokens can be used to access the Speckle API on this
server; they function like ordinary OAuth access tokens.
<b>Treat them like a password!</b>
server; they function like ordinary OAuth access tokens. Use them in your
scripts or apps!
<b>
Treat them like a password: do not post them anywhere where they could
be accessed by others (e.g., public repos).
</b>
</v-card-text>
<v-card-text v-if="$apollo.loading">Loading...</v-card-text>
<v-card-text v-if="tokens">
@@ -13,13 +17,14 @@
v-for="token in tokens"
:key="token.id"
:token="token"
@deleted="refreshList"
/>
</v-list>
</v-card-text>
<v-card-text>
<v-btn @click="tokenDialog = true">new token</v-btn>
<v-dialog v-model="tokenDialog" width="500">
<token-dialog />
<v-dialog v-model="tokenDialog" persistent width="500">
<token-dialog @token-added="refreshList" @close="tokenDialog = false" />
</v-dialog>
</v-card-text>
</v-card>
@@ -55,6 +60,10 @@ export default {
update: (data) => data.user.apiTokens
}
},
methods: {}
methods: {
refreshList() {
this.$apollo.queries.tokens.refetch()
}
}
}
</script>
+50 -13
View File
@@ -1,10 +1,12 @@
<template>
<v-card class="pa-4" color="background2">
<v-card-title class="subtitle-1">
<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-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
@@ -46,8 +48,21 @@
autofocus
></v-text-field>
<br />
<v-btn>Save</v-btn>
<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>
@@ -83,19 +98,41 @@ export default {
(v) => !!v || "Name is required",
(v) => (v && v.length <= 60) || "Name must be less than 60 characters"
],
selectedScopes: []
selectedScopes: [],
fullTokenResult: null
}
},
computed: {
showDialog: {
get() {
return this.show
},
set(value) {
this.$emit("input", value)
methods: {
clearAndClose() {
this.fullTokenResult = null
this.name = null
this.selectedScopes = []
this.$emit("close")
},
async createToken() {
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)
}
}
},
methods: {}
}
}
</script>